Compare commits
83 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 |
@@ -1,21 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
|
||||
# set RTEMS to eg. "4.9" or "4.10"
|
||||
# requires qemu, bison, flex, texinfo, install-info
|
||||
if [ -n "$RTEMS" ]
|
||||
then
|
||||
# find local qemu-system-i386
|
||||
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
|
||||
echo -n "Using QEMU: "
|
||||
type qemu-system-i386 || echo "Missing qemu"
|
||||
EXTRA=RTEMS_QEMU_FIXUPS=YES
|
||||
fi
|
||||
|
||||
make -j2 $EXTRA
|
||||
|
||||
if [ "$TEST" != "NO" ]
|
||||
then
|
||||
make tapfiles
|
||||
make -s test-results
|
||||
fi
|
||||
@@ -1,180 +0,0 @@
|
||||
#!/bin/sh
|
||||
set -e -x
|
||||
|
||||
CURDIR="$PWD"
|
||||
|
||||
QDIR="$HOME/.cache/qemu"
|
||||
|
||||
if [ -n "$RTEMS" -a "$TEST" = "YES" ]
|
||||
then
|
||||
git clone --quiet --branch vme --depth 10 https://github.com/mdavidsaver/qemu.git "$HOME/.build/qemu"
|
||||
cd "$HOME/.build/qemu"
|
||||
|
||||
HEAD=`git log -n1 --pretty=format:%H`
|
||||
echo "HEAD revision $HEAD"
|
||||
|
||||
[ -e "$HOME/.cache/qemu/built" ] && BUILT=`cat "$HOME/.cache/qemu/built"`
|
||||
echo "Cached revision $BUILT"
|
||||
|
||||
if [ "$HEAD" != "$BUILT" ]
|
||||
then
|
||||
echo "Building QEMU"
|
||||
git submodule --quiet update --init
|
||||
|
||||
install -d "$HOME/.build/qemu/build"
|
||||
cd "$HOME/.build/qemu/build"
|
||||
|
||||
"$HOME/.build/qemu/configure" --prefix="$HOME/.cache/qemu/usr" --target-list=i386-softmmu --disable-werror
|
||||
make -j2
|
||||
make install
|
||||
|
||||
echo "$HEAD" > "$HOME/.cache/qemu/built"
|
||||
fi
|
||||
fi
|
||||
|
||||
cat << EOF > $CURDIR/configure/RELEASE.local
|
||||
EPICS_BASE=$HOME/.source/epics-base
|
||||
EOF
|
||||
|
||||
install -d "$HOME/.source"
|
||||
cd "$HOME/.source"
|
||||
|
||||
add_base_module() {
|
||||
MODULE=$1
|
||||
BRANCH=$2
|
||||
( cd epics-base/modules && \
|
||||
git clone --quiet --depth 5 --branch $MODULE/$BRANCH https://github.com/${REPOBASE:-epics-base}/epics-base.git $MODULE && \
|
||||
cd $MODULE && git log -n1 )
|
||||
}
|
||||
|
||||
add_gh_module() {
|
||||
MODULE=$1
|
||||
REPOOWNER=$2
|
||||
REPONAME=$3
|
||||
BRANCH=$4
|
||||
( cd epics-base/modules && \
|
||||
git clone --quiet --depth 5 --branch $BRANCH https://github.com/$REPOOWNER/$REPONAME.git $MODULE && \
|
||||
cd $MODULE && git log -n1 )
|
||||
}
|
||||
|
||||
add_gh_flat() {
|
||||
MODULE=$1
|
||||
REPOOWNER=$2
|
||||
REPONAME=$3
|
||||
BRANCH=$4
|
||||
MODULE_UC=$(echo $MODULE | tr 'a-z' 'A-Z')
|
||||
( git clone --quiet --depth 5 --branch $BRANCH https://github.com/$REPOOWNER/$REPONAME.git $MODULE && \
|
||||
cd $MODULE && git log -n1 )
|
||||
cat < $CURDIR/configure/RELEASE.local > $MODULE/configure/RELEASE.local
|
||||
cat << EOF >> $CURDIR/configure/RELEASE.local
|
||||
${MODULE_UC}=$HOME/.source/$MODULE
|
||||
EOF
|
||||
}
|
||||
|
||||
if [ "$BRBASE" ]
|
||||
then
|
||||
git clone --quiet --depth 5 --branch "$BRBASE" https://github.com/${REPOBASE:-epics-base}/epics-base.git epics-base
|
||||
(cd epics-base && git log -n1 )
|
||||
add_gh_flat pvData ${REPOPVD:-epics-base} pvDataCPP ${BRPVD:-master}
|
||||
add_gh_flat pvAccess ${REPOPVA:-epics-base} pvAccessCPP ${BRPVA:-master}
|
||||
add_gh_flat normativeTypes ${REPONT:-epics-base} normativeTypesCPP ${BRNT:-master}
|
||||
else
|
||||
git clone --quiet --depth 5 --branch core/"${BRCORE:-master}" https://github.com/${REPOBASE:-epics-base}/epics-base.git epics-base
|
||||
( cd epics-base && git log -n1 )
|
||||
add_base_module libcom "${BRLIBCOM:-master}"
|
||||
add_base_module ca "${BRCA:-master}"
|
||||
add_base_module database "${BRDATABASE:-master}"
|
||||
add_gh_module pvData ${REPOPVD:-epics-base} pvDataCPP ${BRPVD:-master}
|
||||
add_gh_module pvAccess ${REPOPVA:-epics-base} pvAccessCPP ${BRPVA:-master}
|
||||
add_gh_module normativeTypes ${REPONT:-epics-base} normativeTypesCPP ${BRNT:-master}
|
||||
fi
|
||||
|
||||
if [ -e $CURDIR/configure/RELEASE.local ]
|
||||
then
|
||||
cat $CURDIR/configure/RELEASE.local
|
||||
fi
|
||||
|
||||
EPICS_HOST_ARCH=`sh epics-base/startup/EpicsHostArch`
|
||||
|
||||
# requires wine and g++-mingw-w64-i686
|
||||
if [ "$WINE" = "32" ]
|
||||
then
|
||||
echo "Cross mingw32"
|
||||
sed -i -e '/CMPLR_PREFIX/d' epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
|
||||
CMPLR_PREFIX=i686-w64-mingw32-
|
||||
EOF
|
||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
||||
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
|
||||
EOF
|
||||
fi
|
||||
|
||||
if [ "$STATIC" = "YES" ]
|
||||
then
|
||||
echo "Build static libraries/executables"
|
||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
||||
SHARED_LIBRARIES=NO
|
||||
STATIC_BUILD=YES
|
||||
EOF
|
||||
fi
|
||||
|
||||
case "$CMPLR" in
|
||||
clang)
|
||||
echo "Host compiler is clang"
|
||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
|
||||
GNU = NO
|
||||
CMPLR_CLASS = clang
|
||||
CC = clang
|
||||
CCC = clang++
|
||||
EOF
|
||||
|
||||
# hack
|
||||
sed -i -e 's/CMPLR_CLASS = gcc/CMPLR_CLASS = clang/' epics-base/configure/CONFIG.gnuCommon
|
||||
|
||||
clang --version
|
||||
;;
|
||||
*)
|
||||
echo "Host compiler is default"
|
||||
gcc --version
|
||||
;;
|
||||
esac
|
||||
|
||||
cat <<EOF >> epics-base/configure/CONFIG_SITE
|
||||
USR_CPPFLAGS += $USR_CPPFLAGS
|
||||
USR_CFLAGS += $USR_CFLAGS
|
||||
USR_CXXFLAGS += $USR_CXXFLAGS
|
||||
EOF
|
||||
|
||||
# set RTEMS to eg. "4.9" or "4.10"
|
||||
# requires qemu, bison, flex, texinfo, install-info
|
||||
if [ -n "$RTEMS" ]
|
||||
then
|
||||
echo "Cross RTEMS${RTEMS} for pc386"
|
||||
install -d /home/travis/.cache
|
||||
curl -L "https://github.com/mdavidsaver/rsb/releases/download/travis-20160306-2/rtems${RTEMS}-i386-trusty-20190306-2.tar.gz" \
|
||||
| tar -C /home/travis/.cache -xj
|
||||
|
||||
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' epics-base/configure/os/CONFIG_SITE.Common.RTEMS
|
||||
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.RTEMS
|
||||
RTEMS_VERSION=$RTEMS
|
||||
RTEMS_BASE=/home/travis/.cache/rtems${RTEMS}-i386
|
||||
EOF
|
||||
cat << EOF >> epics-base/configure/CONFIG_SITE
|
||||
CROSS_COMPILER_TARGET_ARCHS+=RTEMS-pc386
|
||||
EOF
|
||||
|
||||
# find local qemu-system-i386
|
||||
export PATH="$HOME/.cache/qemu/usr/bin:$PATH"
|
||||
echo -n "Using QEMU: "
|
||||
type qemu-system-i386 || echo "Missing qemu"
|
||||
EXTRA=RTEMS_QEMU_FIXUPS=YES
|
||||
fi
|
||||
|
||||
make -j2 -C epics-base $EXTRA
|
||||
|
||||
if [ "$BRBASE" ]
|
||||
then
|
||||
make -j2 -C pvData $EXTRA
|
||||
make -j2 -C pvAccess $EXTRA
|
||||
make -j2 -C normativeTypes $EXTRA
|
||||
fi
|
||||
@@ -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
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
sudo: false
|
||||
dist: trusty
|
||||
language: c++
|
||||
compiler:
|
||||
- gcc
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libreadline6-dev
|
||||
- libncurses5-dev
|
||||
- perl
|
||||
- clang
|
||||
- g++-mingw-w64-i686
|
||||
install:
|
||||
- ./.ci/travis-prepare.sh
|
||||
script:
|
||||
- ./.ci/travis-build.sh
|
||||
env:
|
||||
- BRCORE=master BRLIBCOM=master BRPVD=master BRPVA=master BRNT=master TEST=NO
|
||||
- CMPLR=clang TEST=NO
|
||||
- USR_CXXFLAGS=-std=c++11 TEST=NO
|
||||
- CMPLR=clang USR_CXXFLAGS=-std=c++11 TEST=NO
|
||||
- WINE=32 TEST=NO STATIC=YES
|
||||
- WINE=32 TEST=NO STATIC=NO
|
||||
- RTEMS=4.10 TEST=NO
|
||||
- RTEMS=4.9 TEST=NO
|
||||
- BRBASE=3.16 TEST=NO
|
||||
- BRBASE=3.15 TEST=NO
|
||||
- BRBASE=3.14 TEST=NO
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = pvaClientCPP
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# 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
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
|
||||
# will be relative from the directory where doxygen is started.
|
||||
# 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
|
||||
# path mentioned in the documentation of a class, which tells the reader which
|
||||
@@ -161,7 +161,7 @@ STRIP_FROM_PATH =
|
||||
# specify the list of include paths that are normally passed to the compiler
|
||||
# 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
|
||||
# less readable) file names. This can be useful is your file systems doesn't
|
||||
@@ -765,7 +765,8 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# 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
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@@ -796,7 +797,7 @@ FILE_PATTERNS =
|
||||
# be searched for input files as well.
|
||||
# The default value is: NO.
|
||||
|
||||
RECURSIVE = YES
|
||||
RECURSIVE = NO
|
||||
|
||||
# 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
|
||||
@@ -1035,7 +1036,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# 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
|
||||
# generated HTML page (for example: .htm, .php, .asp).
|
||||
|
||||
@@ -1,23 +1,17 @@
|
||||
pvaClientCPP
|
||||
============
|
||||
# pvaClientCPP
|
||||
|
||||
pvaClient is a synchronous client interface to pvAccess,
|
||||
which is callback based.
|
||||
pvaClient is thus easier to use than pvAccess itself.
|
||||
The **pvaClient** API provides a synchronous client interface that was designed to be easier to use than the original basic pvAccess client API.
|
||||
|
||||
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
|
||||
then just type:
|
||||
- General information about EPICS can be found at the
|
||||
[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
|
||||
|
||||
It can also be built by:
|
||||
|
||||
cp configure/ExampleRELEASE.local configure/RELEASE.local
|
||||
edit configure/RELEASE.local
|
||||
make
|
||||
## Building
|
||||
|
||||
This module is included as a submodule of a full EPICS 7 release and will be compiled during builds of that software.
|
||||
|
||||
@@ -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
|
||||
@@ -2,6 +2,8 @@ TOP=..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
CFG += CONFIG_PVACLIENT_VERSION
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
|
||||
@@ -1,18 +1,87 @@
|
||||
pvaClientCPP Version 4.3.0
|
||||
==========================
|
||||
# pvaClientCPP Module
|
||||
|
||||
Works with pvDataCPP-7.0 and pvAccessCPP-6.0 versions
|
||||
-----------------------------------------------------
|
||||
This document summarizes the changes to the module between releases.
|
||||
|
||||
Will not work with older versions of these modules.
|
||||
## Release 4.8.1 (EPICS 7.0.10, Dec 2025)
|
||||
|
||||
destroy methods removed
|
||||
-----------------------
|
||||
* Fix error message generation code.
|
||||
|
||||
All the destroy methods are removed since implementation is RAII compliant.
|
||||
## Release 4.8.0 (EPICS 7.0.6 Jul 2021)
|
||||
|
||||
API changes to PvaClientMonitor
|
||||
-------------------------------
|
||||
* 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
|
||||
|
||||
@@ -22,7 +91,7 @@ The second argument of method
|
||||
epics::pvData::PVStructurePtr const &pvRequest
|
||||
);
|
||||
|
||||
Is now changed to
|
||||
is now changed to
|
||||
|
||||
static PvaClientMonitorPtr create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
@@ -42,22 +111,16 @@ A new method is also implemented
|
||||
);
|
||||
|
||||
|
||||
pvaClientCPP Version 4.2
|
||||
========================
|
||||
## 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.
|
||||
|
||||
|
||||
|
||||
pvaClientCPP Version 4.1
|
||||
========================
|
||||
|
||||
## 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)
|
||||
@@ -1,5 +0,0 @@
|
||||
NOT FOR DIRECT USE
|
||||
==================
|
||||
|
||||
This directory holds files that are used by doxygen.
|
||||
The files are not meant to be read except via the doxygen documention.
|
||||
@@ -1,146 +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>PvaClient</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClient</h1>
|
||||
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess itself.
|
||||
In addition pvaClient provides many convenience methods.
|
||||
</p>
|
||||
<p>
|
||||
Class <b>PvaClient</b> is a class that is used by all the other pvaClient classes.
|
||||
An application that uses pvaClient must call:</p>
|
||||
<pre>
|
||||
PvaClientPtr pvaClient = PvaClient::get(providers);
|
||||
</pre>
|
||||
<p>
|
||||
before it uses any other pvaClient classes.
|
||||
</p>
|
||||
<p>
|
||||
This is a singleton method, i. e. only one instance of PvaClient is created.
|
||||
</p>
|
||||
<p>
|
||||
<b>pvaClient</b> must not be deleted until the client no longer wants to use any part
|
||||
of pvaClient.
|
||||
</p>
|
||||
<p>
|
||||
<b>providers</b> is a blank separated set of provider names.
|
||||
For example:</p>
|
||||
<pre>
|
||||
PvaClientPtr pvaClient = PvaClient::get("ca pva");
|
||||
</pre>
|
||||
<p>
|
||||
The providers <b>ca</b> and <b>pva</b> are special.
|
||||
For each of these a client context is created when the <b>PvaClient</b>
|
||||
is constructed and the context destroyed when <b>PvaClient</b> is deleted.
|
||||
</p>
|
||||
<h2>Channel Caching</h2>
|
||||
<p>
|
||||
<b>PvaClient</b> has a method:
|
||||
</p>
|
||||
<pre>
|
||||
PvaClientChannelPtr channel(
|
||||
string const & channelName,
|
||||
string const &providerName = "pva",
|
||||
double timeOut = 5.0);
|
||||
</pre>
|
||||
<p>
|
||||
This method creates a
|
||||
<b>PvaClientChannel</b> and then connects to the channel.
|
||||
</p>
|
||||
<p>
|
||||
If a call is successful then multiple calls to the same channelName and providerName
|
||||
share the same PvaClientChannel, i. e. the PvaClientChannel is cached.
|
||||
</p>
|
||||
<p>
|
||||
<b>pvaClientChannelGet</b> and <b>pvaClientChannelPut</b> also implement caching.
|
||||
</p>
|
||||
<p>
|
||||
For example consider a client that makes multiple calls like:
|
||||
</p>
|
||||
<pre>
|
||||
double value;
|
||||
value = pva->channel(channelName)->get()->getData()->getDouble();
|
||||
...
|
||||
value = pva->channel(channelName)->get()->getData()->getDouble();
|
||||
</pre>
|
||||
<p>
|
||||
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
|
||||
The second call reuses the cached PvaClientChannel and PvaClientGet.
|
||||
</p>
|
||||
<h2>Non Cached Channels</h2>
|
||||
<p>
|
||||
<b>PvaClient</b> has a method:
|
||||
</p>
|
||||
<pre>
|
||||
PvaClientChannelPtr createChannel(
|
||||
string const & channelName,
|
||||
string const &providerName = "pva");
|
||||
</pre>
|
||||
<p>
|
||||
This method is just creates a new PvaClientChannel and returns it to the caller.
|
||||
The caller must call the PvaClientChannel connect methods.
|
||||
</p>
|
||||
|
||||
<h2>Blocking vs Non-Blocking Methods</h2>
|
||||
<p>Each component of pvaClient provides a set of blocking and non-blocking calls.
|
||||
For example several components (examples are <b>PvaClientChannel</b> and <b>PvaChannelGet</b>)
|
||||
have methods:</p>
|
||||
<dl>
|
||||
<dt>connect</dt>
|
||||
<dd>
|
||||
This calls issueConnect and then waitConnect.
|
||||
If waitConnect fails an exception is thrown.
|
||||
Since waitConnect is a blocking method so is this.
|
||||
</dd>
|
||||
<dt>issueConnect</dt>
|
||||
<dd>
|
||||
This is a request to connect, i. e. issue a request to the server to create something
|
||||
on the server. This is a non blocking call.
|
||||
</dd>
|
||||
<dt>waitConnect</dt>
|
||||
<dd>
|
||||
This waits for the server to respond to issueConnect.
|
||||
It blocks until the server responds or a timeout occurs.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,123 +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>PvaClientChannel</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientChannel</h1>
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
pvaClientChannel is a synchronous wrapper for the pvAccess::Channel API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess::Channel itself.
|
||||
</p>
|
||||
<p>An instance of <b>PvaClientChannel</b> connects to a single channel.
|
||||
An instance can only be created via class <b>PvaClient</b> which has both synchronous methods, which block, and non blocking methods.
|
||||
The synchrouous methods block until a connection is made to the channel and throw an exception if a
|
||||
timeout occurs while trying to make a connection.
|
||||
The non blocking methods leave connection to the caller.
|
||||
</p>
|
||||
<p><b>PvaClientChannel</b> has methods:</p>
|
||||
<dl>
|
||||
<dt>Connect to channel</dt>
|
||||
<dd>These can be called indirectly by a blocking request to <b>PvaClient</b>
|
||||
or by the client if a non blocking request is made to <b>PvaClient</b>.
|
||||
</dd>
|
||||
<dt>Channel state change requester</dt>
|
||||
<dd>The client can provide a callback that is called each time the connection state
|
||||
of the channel changes.
|
||||
</dd>
|
||||
<dt>Creating all of the following</dt>
|
||||
<dd>
|
||||
<pre>
|
||||
PvaClientField NOT IMPLEMENTED
|
||||
PvaClientProcess
|
||||
PvaClientGet
|
||||
PvaClientPut
|
||||
PvaClientPutGet
|
||||
PvaClientMonitor
|
||||
PvaClientArray NOT IMPLEMENTED
|
||||
PvaClientRPC
|
||||
</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>Connect: Blocking vs Non-Blocking </h2>
|
||||
<p><b>PvaClientChannel</b> has methods:</p>
|
||||
<dl>
|
||||
<dt>connect</dt>
|
||||
<dd>
|
||||
This calls issueConnect and then waitConnect.
|
||||
If waitConnect fails an exception is thrown.
|
||||
Since waitConnect is a blocking method so is this.
|
||||
</dd>
|
||||
<dt>issueConnect</dt>
|
||||
<dd>
|
||||
This is a request to connect to the channel. This is a non blocking call.
|
||||
</dd>
|
||||
<dt>waitConnect</dt>
|
||||
<dd>
|
||||
This waits for the server to respond to issueConnect.
|
||||
It blocks until the server responds or a timeout occurs.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2>Get and Put Caching</h2>
|
||||
<p>
|
||||
<b>PvaClientChannel</b> has methods:
|
||||
</p>
|
||||
<pre>
|
||||
PvaClientGetPtr get(std::string const & request);
|
||||
PvaClientPutPtr put(std::string const & request);
|
||||
</pre>
|
||||
<p>
|
||||
Each of these caches.
|
||||
For example all calls to <b>get</b> with the same <b>request</b> will share the same
|
||||
<b>PvaChannelGet</b>
|
||||
</p>
|
||||
<p>
|
||||
For example consider a client that makes multiple calls like:
|
||||
</p>
|
||||
<pre>
|
||||
double value;
|
||||
value = pva->channel(channelName)->get()->getData()->getDouble();
|
||||
...
|
||||
value = pva->channel(channelName)->get()->getData()->getDouble();
|
||||
</pre>
|
||||
<p>
|
||||
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
|
||||
The second call reuses the cached PvaClientChannel and PvaClientGet.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,81 +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>PvaClientChannelStateChangeRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientChannelStateChangeRequester</h1>
|
||||
|
||||
<p>This class has the single method <b>channelStateChange</b>.
|
||||
It is called each time the channel connection status changes.
|
||||
</p>
|
||||
<p>
|
||||
<b>NOTE:</b>
|
||||
The implementation must not call a method that blocks waiting for a response from the server.
|
||||
It it does the client may be blocked forever.
|
||||
</p>
|
||||
<p>
|
||||
An example of illegal code is:
|
||||
</p>
|
||||
<pre>
|
||||
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
|
||||
{
|
||||
if(isConnected&&!pvaClientPut)
|
||||
{
|
||||
pvaClientPut = pvaClientChannel->createPut(request);
|
||||
pvaClientPut->connect();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
This is illegal because the call to <b>connect</b> blocks.
|
||||
</p>
|
||||
<p>The following is an example of legal code:
|
||||
</p>
|
||||
<pre>
|
||||
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
|
||||
{
|
||||
if(isConnected&&!pvaClientPut)
|
||||
{
|
||||
pvaClientPut = pvaClientChannel->createPut(request);
|
||||
pvaClientPut->issueConnect();
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
<p>This is legal code because neither <b>createPut</b> or <b>issueConnect</b>
|
||||
blocks.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,74 +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>PvaClientGet</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientGet</h1>
|
||||
|
||||
|
||||
<p>
|
||||
pvaClientGet is a synchronous wrapper for the pvAccess::ChannelGet API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess::ChannelGet itself.
|
||||
</p>
|
||||
<p>An instance of PvaClientGet is created via a call to one of the following:</p>
|
||||
<pre>
|
||||
class PvaClientChannel
|
||||
...
|
||||
{
|
||||
...
|
||||
PvaClientGetPtr get(std::string const & request = "field(value,alarm,timeStamp)");
|
||||
PvaClientGetPtr createGet(std::string const & request = "");
|
||||
PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
...
|
||||
};
|
||||
<p>An instance of <b>PvaClientGet</b> connects to a single channel.
|
||||
<b>PvaClientGet</b> has both synchronous methods, which block, and non blocking methods.
|
||||
</p>
|
||||
<p><b>PvaClientChannel</b> has methods:</p>
|
||||
<pre>
|
||||
connect Calls issueConnect and then waitConnect.
|
||||
issueConnect issues a request to the server to create the server side of ChannelPut.
|
||||
waitConnect blocks until server responds that it has created the ChannelPut.
|
||||
get Calls issueGet and then waitGet.
|
||||
issueGet issues a get request to the server.
|
||||
waitGet waits until the server send a message that the get is complete.
|
||||
getData get the data.
|
||||
</pre>
|
||||
<p>
|
||||
<b>issueConnect</b> and <b>issueGet</b> do not block.
|
||||
All other methods can block.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,63 +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>PvaClientGetData</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientGetData</h1>
|
||||
|
||||
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
|
||||
It provides methods:</p>
|
||||
<pre>
|
||||
getStructure Get the introspection interface for data returned from server
|
||||
getPVStructure Get the complete set of data returned from the server.
|
||||
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
|
||||
showChanged Show all the fields that have changed value since the last get,
|
||||
getAlarm If a alarm field is available get it.
|
||||
getTimeStamp If a timeStamp field is available get it.
|
||||
hasValue Does the PVStructure have a top level field named value
|
||||
NOTE: The following only apply if hasValue is true.
|
||||
isValueScalar Is the value field a scalar?
|
||||
isValueScalarArray Is the value field a scalar array?
|
||||
getValue Get the value field.
|
||||
getScalarValue Get a scalar value field.
|
||||
getArrayValue Get an array value field.
|
||||
getScalarArrayValue Get a scalar array value field.
|
||||
getDouble Get scalar value field as a double.
|
||||
getString Get value field as a string.
|
||||
getDoubleArray Get value field as a double array.
|
||||
getStringArray Get value field as a string array.
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,59 +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>PvaClientGetRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientGetRequester</h1>
|
||||
|
||||
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientGet</b>.
|
||||
It has the methods:</p>
|
||||
<pre>
|
||||
virtual void channelGetConnect(
|
||||
const Status& status,
|
||||
PvaClientGetPtr const & clientGet) {}
|
||||
virtual void getDone(
|
||||
const Status& status,
|
||||
PvaClientGetPtr const & clientGet) = 0;
|
||||
</pre>
|
||||
|
||||
<p>The client must call</p>
|
||||
<pre>
|
||||
pvaClientGet->setRequester(shared_from_this());
|
||||
</pre>
|
||||
<p>
|
||||
after creating an instance of PvaClientGet.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,106 +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>PvaClientMonitor</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientMonitor</h1>
|
||||
<p>
|
||||
<b>NOTE:</b> This is a work in progress.
|
||||
</p>
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
This provides an easier way to create a monitor on a channel than to use pvAccessCPP itself.
|
||||
It provides two main ways to create a monitor:
|
||||
</p>
|
||||
<h3>The client first creates a PvaClientMonitorChannel and then creates a monitor</h3>
|
||||
The client calls:
|
||||
<pre>
|
||||
static PvaClientMonitorPtr create(
|
||||
PvaClientMonitorPtr const &PvaClientMonitor,
|
||||
PvaClientMonitorChannelPtr const & PvaClientMonitorChannel,
|
||||
epics::pvData::PVStructurePtr const &pvRequest
|
||||
);
|
||||
|
||||
where
|
||||
|
||||
PvaClientMonitor
|
||||
The PvaClientMonitor.
|
||||
|
||||
PvaClientMonitorChannel
|
||||
The PvaClientMonitorChannel that has already been created by the client.
|
||||
|
||||
pvRequest
|
||||
The pvRequest for creating the monitor.
|
||||
</pre>
|
||||
With this method the monitor is created and started.
|
||||
This method blocks while the monitor is created.
|
||||
<h3>The client provides names for a channel and a provider</h3>
|
||||
The client calls:
|
||||
<pre>
|
||||
static PvaClientMonitorPtr create(
|
||||
PvaClientMonitorPtr const &PvaClientMonitor,
|
||||
std::string const & channelName,
|
||||
std::string const & providerName,
|
||||
std::string const & request,
|
||||
PvaClientMonitorChannelStateChangeRequesterPtr const & stateChangeRequester,
|
||||
PvaClientMonitorRequesterPtr const & monitorRequester
|
||||
);
|
||||
|
||||
where
|
||||
|
||||
PvaClientMonitor
|
||||
The PvaClientMonitor.
|
||||
|
||||
channelName
|
||||
The name of the channel.
|
||||
|
||||
providerName
|
||||
The name of the provider
|
||||
|
||||
request
|
||||
The request for creating the monitor
|
||||
|
||||
stateChangeRequester
|
||||
The client supplied state change requester.
|
||||
This will be called each time a state change for the channel occurs.
|
||||
|
||||
monitorRequester
|
||||
The client supplied monitor requester.
|
||||
This is called each time a new monitor event is available.
|
||||
</pre>
|
||||
With this method a pvaChannel is created and after it connects a pvaMonitor is created and started.
|
||||
This method never blocks.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,66 +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>PvaClientMonitorData</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientMonitorData</h1>
|
||||
|
||||
|
||||
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
|
||||
It provides methods:</p>
|
||||
<pre>
|
||||
getStructure Get the introspection interface for data returned from server
|
||||
getPVStructure Get the complete set of data returned from the server.
|
||||
getChangedBitSet Get the bitSet that shows which fields have a new value since last monitor event.
|
||||
getOverrunBitSet Get the bitSet that shows which fields have changed more than once since last monitor event.
|
||||
showChanged Show all the fields that have changed value since the last monitor event,
|
||||
showChanged Show all the fields that have changed value more than once since last monitor event.
|
||||
getAlarm If a alarm field is available get it.
|
||||
getTimeStamp If a timeStamp field is available get it.
|
||||
hasValue Does the PVStructure have a top level field named value
|
||||
NOTE: The following only apply if hasValue is true.
|
||||
isValueScalar Is the value field a scalar?
|
||||
isValueScalarArray Is the value field a scalar array?
|
||||
getValue Get the value field.
|
||||
getScalarValue Get a scalar value field.
|
||||
getArrayValue Get an array value field.
|
||||
getScalarArrayValue Get a scalar array value field.
|
||||
getDouble Get scalar value field as a double.
|
||||
getString Get value field as a string.
|
||||
getDoubleArray Get value field as a double array.
|
||||
getStringArray Get value field as a string array.
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,65 +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>PvaClientMonitorRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientMonitorRequester</h1>
|
||||
|
||||
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientMonitor</b>.
|
||||
It has the methods:</p>
|
||||
<pre>
|
||||
virtual void monitorConnect(
|
||||
const Status& status,
|
||||
PvaClientMonitorPtr const & clientMonitor,
|
||||
StructureConstPtr const & structure) {}
|
||||
virtual void event(
|
||||
PvaClientMonitor const & clientGet) = 0;
|
||||
virtual void unlisten()
|
||||
{
|
||||
std::cerr << "PvaClientMonitorRequester::unlisten called"
|
||||
<< " but no PvaClientMonitorRequester::unlisten\n";
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>The client must call</p>
|
||||
<pre>
|
||||
pvaClientMonitor->setRequester(shared_from_this());
|
||||
</pre>
|
||||
<p>
|
||||
after creating an instance of PvaClientMonitor.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,71 +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>PvaClientProcess</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientProcess</h1>
|
||||
|
||||
<p>
|
||||
pvaClientProcess is a synchronous wrapper for the pvAccess::ChannelProcess API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess::ChannelProcess itself.
|
||||
</p>
|
||||
<p>An instance of PvaClientProcess is created via a call to one of the followimg:</p>
|
||||
<pre>
|
||||
class PvaClientChannel
|
||||
...
|
||||
{
|
||||
...
|
||||
PvaClientProcessPtr createProcess(std::string const & request = "");
|
||||
PvaClientProcessPtr createProcess(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
...
|
||||
};
|
||||
<p>An instance of <b>PvaClientProcess</b> connects to a single channel.
|
||||
<b>PvaClientProcess</b> has both synchronous methods, which block, and non blocking methods.
|
||||
</p>
|
||||
<p><b>PvaClientChannel</b> has methods:</p>
|
||||
<pre>
|
||||
connect Calls issueConnect and then waitConnect.
|
||||
issueConnect issues a request to the server to create the server side of ChannelPut.
|
||||
waitConnect blocks until server responds that it has created the ChannelPut.
|
||||
process Calls issueProcess and then waitProcess.
|
||||
issueProcess issues a process request to the server.
|
||||
waitProcess waits until the server send a message that the process is complete.
|
||||
</pre>
|
||||
<p>
|
||||
<b>issueConnect</b> and <b>issueProcess</b> do not block.
|
||||
All other methods can block.
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,82 +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>PvaClientChannelPut</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientChannelPut</h1>s
|
||||
|
||||
<p>
|
||||
pvaClientPut is a synchronous wrapper for the pvAccess::ChannelPut API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess::ChannelPut itself.
|
||||
</p>
|
||||
<p>
|
||||
<b>NOTE:</b>
|
||||
Except for union fields pvaClientPut takes care of modifying the bitSet associated with
|
||||
the data sent to the server.
|
||||
</p>
|
||||
<p>An instance of PvaClientPut is created via a call to one of the followimg:</p>
|
||||
<pre>
|
||||
class PvaClientChannel
|
||||
...
|
||||
{
|
||||
...
|
||||
PvaClientPutPtr put(std::string const & request = "field(value,alarm,timeStamp)");
|
||||
PvaClientPutPtr createPut(std::string const & request = "");
|
||||
PvaClientPutPtr createPut(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
...
|
||||
};
|
||||
<p>An instance of <b>PvaClientPut/b> connects to a single channel.
|
||||
<b>PvaClientPut</b> has both synchronous methods, which block, and non blocking methods.
|
||||
</p>
|
||||
<p><b>PvaClientPut</b> has methods:</p>
|
||||
<pre>
|
||||
connect Calls issueConnect and then waitConnect.
|
||||
issueConnect issues a request to the server to create the server side of ChannelPut.
|
||||
waitConnect blocks until server responds that it has created the ChannelPut.
|
||||
get Calls issueGet and then waitGet.
|
||||
issueGet issues a request to the server to get the latest data.
|
||||
waitGet waits until the server send a message that the get is complete.
|
||||
put Calls issuePut and then waitPut.
|
||||
issuePut issues a put request to the server.
|
||||
waitPut waits until the server send a message that the put is complete.
|
||||
getData get the data.
|
||||
</pre>
|
||||
<p>
|
||||
Note that <b>issueConnect</b>, <b>issueGet</b> and <b>issuePut</b> do not block but all other methods
|
||||
do block.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,75 +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>PvaClientPutData</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientPutData</h1>
|
||||
|
||||
<p>This class provides access to data to send to the server via a <b>PvaChannelPut</b>
|
||||
It is created by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
|
||||
This the client only gets access to an instance by getting it from <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
|
||||
<p>
|
||||
<p>Note also that for all field types except <b>union</b> the <b>BitSet</b> for the data is updated
|
||||
by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b> whenever the client changes a field.
|
||||
For a <b>union</b> or <b>unionArray</b> field the client must update the <b>BitSet</b>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
PvaClientPutData provides methods:</p>
|
||||
<pre>
|
||||
getStructure Get the introspection interface for data sent to server
|
||||
getPVStructure Get the complete set of data sent to the server.
|
||||
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
|
||||
showChanged Show all the fields that have changed value since the last get,
|
||||
getAlarm If a alarm field is available get it.
|
||||
getTimeStamp If a timeStamp field is available get it.
|
||||
hasValue Does the PVStructure have a top level field named value
|
||||
NOTE: The following only apply if hasValue is true.
|
||||
isValueScalar Is the value field a scalar?
|
||||
isValueScalarArray Is the value field a scalar array?
|
||||
getValue Get the value field.
|
||||
getScalarValue Get a scalar value field.
|
||||
getArrayValue Get an array value field.
|
||||
getScalarArrayValue Get a scalar array value field.
|
||||
getDouble Get scalar value field as a double.
|
||||
getString Get value field as a string.
|
||||
getDoubleArray Get value field as a double array.
|
||||
getStringArray Get value field as a string array.
|
||||
putDouble Put scalar value field as a double.
|
||||
putString Put value field as a string.
|
||||
putDoubleArray Put value field as a double array.
|
||||
putStringArray Put value field as a string array.
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,85 +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>PvaClientPutGetGet</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientPutGetGet</h1>
|
||||
|
||||
<p>
|
||||
pvaClientPutGet is a synchronous wrapper for the pvAccess::ChannelPutGet API, which is a callback based API.
|
||||
Thus it is easier to use than pvAccess::ChannelPut itself.
|
||||
</p>
|
||||
<p>
|
||||
<b>NOTE:</b>
|
||||
Except for union fields pvaClientPutGet takes care of modifying the bitSet associated with
|
||||
the data sent to the server.
|
||||
</p>
|
||||
<p>An instance of PvaClientPutGet is created via a call to one of the followimg:</p>
|
||||
<pre>
|
||||
class PvaClientChannel
|
||||
...
|
||||
{
|
||||
...
|
||||
PvaClientPutGetPtr createPutGet(std::string const & request);
|
||||
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
...
|
||||
};
|
||||
<p>An instance of <b>PvaClientPutGet</b> connects to a single channel.
|
||||
<b>PvaClientPutGet</b> has both synchronous methods, which block, and non blocking methods.
|
||||
</p>
|
||||
<p><b>PvaClientPutGet</b> has methods:</p>
|
||||
<pre>
|
||||
connect calls issueConnect and then waitConnect.
|
||||
issueConnect issues a request to the server to create the server side of ChannelPut.
|
||||
waitConnect blocks until server responds that it has created the ChannelPut.
|
||||
putGet call issuePutGet and then waitPutGet.
|
||||
issuePutGet issue a putGet and return immediately.
|
||||
waitPutGet wait until putGet completes.
|
||||
getGet calls issueGetGet and then waitGetGet.
|
||||
issueGetGet issues a request to the server to get the latest data for the get data.
|
||||
waitGetGet waits until the server send a message that the getGet is complete.
|
||||
getPut calls issueGetPut and then waitGetPut.
|
||||
issueGetPut issues a request to the server to get the latest data for the put data.
|
||||
waitGetPut waits until the server send a message that the getPut is complete.
|
||||
getPutData get the put portion of the data.
|
||||
getGetData get the get portion of the data.
|
||||
</pre>
|
||||
<p>
|
||||
<b>issueConnect</b>, <b>issuePutGet</b>, <b>issueGetGet</b> and <b>issueGetPut</b> do not block.
|
||||
All other methods can block.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,66 +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>PvaClientPutGetRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientPutGetRequester</h1>
|
||||
|
||||
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientPut</b>.
|
||||
It has the methods:</p>
|
||||
<pre>
|
||||
virtual void channelPutGetConnect(
|
||||
const Status& status,
|
||||
PvaClientPutGetPtr const & clientPutGet) {}
|
||||
virtual void putGetDone(
|
||||
const Status& status,
|
||||
PvaClientPutGetPtr const & clientPutGet) {}
|
||||
virtual void getPutDone(
|
||||
const Status& status,
|
||||
PvaClientPutGetPtr const & clientPutGet) = 0;
|
||||
virtual void getGetDone(
|
||||
const Status& status,
|
||||
PvaClientPutGetPtr const & clientPutGet) = 0;
|
||||
</pre>
|
||||
|
||||
<p>The client must call</p>
|
||||
<pre>
|
||||
pvaClientPutGet->setRequester(shared_from_this());
|
||||
</pre>
|
||||
<p>
|
||||
after creating an instance of PvaClientPutGet.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,63 +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>PvaClientPutRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientPutRequester</h1>
|
||||
|
||||
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientPut</b>.
|
||||
It has the methods:</p>
|
||||
<pre>
|
||||
virtual void channelPutConnect(
|
||||
const Status& status,
|
||||
PvaClientPutPtr const & clientPut) {}
|
||||
virtual void getDone(
|
||||
const Status& status,
|
||||
PvaClientPutPtr const & clientPut) {}
|
||||
virtual void putDone(
|
||||
const Status& status,
|
||||
PvaClientPutPtr const & clientPut) = 0;
|
||||
</pre>
|
||||
|
||||
<p>The client must call</p>
|
||||
<pre>
|
||||
pvaClientPut->setRequester(shared_from_this());
|
||||
</pre>
|
||||
<p>
|
||||
after creating an instance of PvaClientPut.
|
||||
</p>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,44 +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>PvaClientRPC</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientRPC</h1>
|
||||
|
||||
<p>
|
||||
<b>Not Yet Written</b>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,44 +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>PvaClientRPCRequester</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 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>PvaClientRPCRequester</h1>
|
||||
|
||||
<p>
|
||||
<b>Not Yet Written</b>
|
||||
</p>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
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>
|
||||
@@ -6,9 +6,9 @@
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>EPICS pvaClientCPP</title>
|
||||
<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"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
href="https://mrkraimer.github.io/website/css/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
@@ -18,7 +18,7 @@
|
||||
/*]]>*/</style>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
|
||||
<div class="head">
|
||||
<h1>EPICS pvaClientCPP</h1>
|
||||
<h2 class="nocount">Release 4.3.0 - 2017-12-14</h2>
|
||||
<h2 class="nocount">Release 4.8 - March 2021</h2>
|
||||
|
||||
<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
|
||||
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
|
||||
@@ -41,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.
|
||||
</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.
|
||||
Additional methods provide access to the full features of pvAccess.
|
||||
</p>
|
||||
@@ -62,13 +62,20 @@ The data for the channels is presented via normative type NTMultiChannel.
|
||||
|
||||
</div> <!-- head -->
|
||||
|
||||
<div id="contents" class="contents">
|
||||
<div id="contents" class="contents">
|
||||
<hr />
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
pvaClientCPP is one of the components of
|
||||
<a href="http://epics-pvdata.sourceforge.net">
|
||||
EPICS Version 4
|
||||
Documentation for pvaClientCPP is available at:
|
||||
<a
|
||||
href="https://mrkraimer.github.io/website/developerGuide/pvaClient/pvaClientCPP.html">
|
||||
pvaClient
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
pvaClientCPP is one of the components of
|
||||
<a href="https://epics-controls.org/resources-and-support/base/epics-7/">
|
||||
EPICS-7
|
||||
</a>
|
||||
</p>
|
||||
<p>This document is only a guide to help locate code and documentation related to pvaClientCPP
|
||||
@@ -79,7 +86,7 @@ It is intended for developers that want to use pvaClientCPP.
|
||||
<h2>Developer Guide</h2>
|
||||
<p>A guide for developers is available at
|
||||
<a
|
||||
href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGuide.html">
|
||||
href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html">
|
||||
developerGuide
|
||||
</a>
|
||||
</p>
|
||||
|
||||
@@ -21,14 +21,7 @@ installE4 () {
|
||||
local module=$1
|
||||
local branch=$2
|
||||
|
||||
# If microbench version does not exist, try without
|
||||
if [ "${MB}" = "WITH_MICROBENCH" ]; then
|
||||
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||
fi
|
||||
else
|
||||
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
|
||||
fi
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -6,12 +6,13 @@ include $(TOP)/configure/CONFIG
|
||||
LIBRARY += pvaClient
|
||||
|
||||
# shared library ABI version.
|
||||
SHRLIB_VERSION ?= 4.3.0
|
||||
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 += pvaClientData.cpp
|
||||
LIBSRCS += pvaClientPutData.cpp
|
||||
LIBSRCS += pvaClientGetData.cpp
|
||||
LIBSRCS += pvaClientMonitorData.cpp
|
||||
|
||||
+200
-337
@@ -17,13 +17,13 @@
|
||||
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <pv/requester.h>
|
||||
#include <pv/status.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvCopy.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
@@ -36,15 +36,17 @@
|
||||
|
||||
#ifdef pvaClientEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvaClientEpicsExportSharedSymbols
|
||||
# undef pvaClientEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
class PvaClient;
|
||||
typedef std::tr1::shared_ptr<PvaClient> PvaClientPtr;
|
||||
class PvaClientData;
|
||||
typedef std::tr1::shared_ptr<PvaClientData> PvaClientDataPtr;
|
||||
class PvaClientGetData;
|
||||
typedef std::tr1::shared_ptr<PvaClientGetData> PvaClientGetDataPtr;
|
||||
class PvaClientPutData;
|
||||
@@ -56,8 +58,6 @@ typedef std::tr1::shared_ptr<PvaClientChannelStateChangeRequester> PvaClientChan
|
||||
typedef std::tr1::weak_ptr<PvaClientChannelStateChangeRequester> PvaClientChannelStateChangeRequesterWPtr;
|
||||
class PvaClientChannel;
|
||||
typedef std::tr1::shared_ptr<PvaClientChannel> PvaClientChannelPtr;
|
||||
class PvaClientField;
|
||||
typedef std::tr1::shared_ptr<PvaClientField> PvaClientFieldPtr;
|
||||
class PvaClientProcessRequester;
|
||||
typedef std::tr1::shared_ptr<PvaClientProcessRequester> PvaClientProcessRequesterPtr;
|
||||
typedef std::tr1::weak_ptr<PvaClientProcessRequester> PvaClientProcessRequesterWPtr;
|
||||
@@ -83,8 +83,6 @@ typedef std::tr1::shared_ptr<PvaClientMonitor> PvaClientMonitorPtr;
|
||||
class PvaClientMonitorRequester;
|
||||
typedef std::tr1::shared_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterPtr;
|
||||
typedef std::tr1::weak_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterWPtr;
|
||||
class PvaClientArray;
|
||||
typedef std::tr1::shared_ptr<PvaClientArray> PvaClientArrayPtr;
|
||||
class PvaClientRPC;
|
||||
typedef std::tr1::shared_ptr<PvaClientRPC> PvaClientRPCPtr;
|
||||
class PvaClientRPCRequester;
|
||||
@@ -99,7 +97,6 @@ typedef std::tr1::shared_ptr<PvaClientChannelCache> PvaClientChannelCachePtr;
|
||||
/**
|
||||
* @brief pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClient.html">Overview of PvaClient</a>
|
||||
*/
|
||||
class epicsShareClass PvaClient :
|
||||
public epics::pvData::Requester,
|
||||
@@ -117,10 +114,11 @@ public:
|
||||
* @return shared pointer to the single instance.
|
||||
*/
|
||||
static PvaClientPtr get(std::string const & providerNames = "pva ca");
|
||||
/** @brief Get the requester name.
|
||||
* @return The name.
|
||||
/** @brief Create an instance of PvaClient with providerName "pva ca".
|
||||
* @return shared pointer to the single instance
|
||||
* @deprecated This method will go away in future versions. Use get instead.
|
||||
*/
|
||||
std::string getRequesterName();
|
||||
static PvaClientPtr create() EPICS_DEPRECATED;
|
||||
/** @brief A new message.
|
||||
*
|
||||
* If a requester is set then it is called otherwise message is displayed
|
||||
@@ -148,18 +146,24 @@ public:
|
||||
* @param channelName The channelName.
|
||||
* @param providerName The provider.
|
||||
* @return The interface.
|
||||
* @throw runtime_error if connection fails.
|
||||
*/
|
||||
PvaClientChannelPtr createChannel(
|
||||
std::string const & channelName,
|
||||
std::string const & providerName = "pva");
|
||||
|
||||
|
||||
/** @brief Set a requester.
|
||||
*
|
||||
* The default is for PvaClient to handle messages by printing to System.out.
|
||||
* @param requester The requester.
|
||||
*/
|
||||
void setRequester(epics::pvData::RequesterPtr const & requester);
|
||||
/** @brief Get the requester name.
|
||||
*
|
||||
* If client calls setRequester then the client supplies the name.
|
||||
* Otherwise the name is pvaClient.
|
||||
* @return The name.
|
||||
*/
|
||||
std::string getRequesterName();
|
||||
/** @brief Clear the requester. PvaClient will handle messages.
|
||||
*/
|
||||
void clearRequester();
|
||||
@@ -196,10 +200,9 @@ class PvaClientPutCache;
|
||||
typedef std::tr1::shared_ptr<PvaClientPutCache> PvaClientPutCachePtr;
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief A callback for change in connection status.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientChannelStateChangeRequester.html">Overview of PvaClientChannelStateChangeRequester</a>
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvaClientChannelStateChangeRequester
|
||||
@@ -220,10 +223,9 @@ public:
|
||||
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief An easy to use alternative to directly calling the Channel methods of pvAccess.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientChannel.html">Overview of PvaClientChannel</a>
|
||||
*/
|
||||
|
||||
class epicsShareClass PvaClientChannel :
|
||||
@@ -237,7 +239,7 @@ public:
|
||||
*/
|
||||
~PvaClientChannel();
|
||||
/** @brief Set a client stateChangeRequester.
|
||||
*
|
||||
*
|
||||
* @param stateChangeRequester The client stateChangeRequester implementation.
|
||||
*/
|
||||
void setStateChangeRequester(PvaClientChannelStateChangeRequesterPtr const &stateChangeRequester);
|
||||
@@ -268,13 +270,6 @@ public:
|
||||
* @return status.
|
||||
*/
|
||||
epics::pvData::Status waitConnect(double timeout = 5.0);
|
||||
/** @brief Create a PvaClientField for the specified subField.
|
||||
*
|
||||
* @param subField The desired subField, i. e. "field.field...."
|
||||
* An empty string, i. e. "", asks for the entire top level struture as defined by the server.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientFieldPtr createField(std::string const & subField = "");
|
||||
/** @brief First call createRequest as implemented by pvDataCPP and then call the next method.
|
||||
*
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
@@ -282,7 +277,7 @@ public:
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
PvaClientProcessPtr createProcess(std::string const & request = "");
|
||||
/** Creates a PvaClientProcess.
|
||||
/** Creates a PvaClientProcess.
|
||||
*
|
||||
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
|
||||
* @return The interface.
|
||||
@@ -306,13 +301,44 @@ public:
|
||||
PvaClientGetPtr createGet(std::string const & request = "field(value,alarm,timeStamp)");
|
||||
/** @brief Creates an PvaClientGet.
|
||||
*
|
||||
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
|
||||
* @param pvRequest The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The interface.
|
||||
* @return The interface.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
/** @brief Get the value as a double.
|
||||
*
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
double getDouble(std::string const & request = "field(value)");
|
||||
/** Get the value as a string.
|
||||
*
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
std::string getString(std::string const & request = "field(value)");
|
||||
/** @brief Get the value as a double array.
|
||||
*
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::shared_vector<const double> getDoubleArray(
|
||||
std::string const & request = "field(value)");
|
||||
/** @brief Get the value as a string array.
|
||||
*
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::shared_vector<const std::string> getStringArray(
|
||||
std::string const & request = "field(value)");
|
||||
/** @brief create a PvaClientPut.
|
||||
*
|
||||
*
|
||||
* Get a cached PvaClientPut or create and connect to a new PvaClientPut.
|
||||
* Then call it's get method.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
@@ -334,6 +360,44 @@ public:
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientPutPtr createPut(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
/** @brief Put the value as a double.
|
||||
*
|
||||
* @param value The new value.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void putDouble(double value,std::string const & request = "field(value)");
|
||||
/** @brief Put the value as a string.
|
||||
*
|
||||
* @param value The new value.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void putString(std::string const & value,std::string const & request = "field(value)");
|
||||
/** @brief Copy the array to the value field.
|
||||
*
|
||||
* @param value The new value.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void putDoubleArray(
|
||||
epics::pvData::shared_vector<const double> const & value,
|
||||
std::string const & request = "field(value)");
|
||||
/** @brief Copy array to the value field.
|
||||
*
|
||||
* @param value The new value.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void putStringArray(
|
||||
epics::pvData::shared_vector<const std::string> const & value,
|
||||
std::string const & request = "field(value)");
|
||||
/** @brief Copy array to the value field.
|
||||
* @param value The data used to update the channel value.
|
||||
* @param request The request as a string to pass to createRequest.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void putStringArray(std::vector<std::string> const & value,std::string const & request = "field(value)");
|
||||
/** @brief create a PvaClientPutGet.
|
||||
*
|
||||
* First call createRequest as implemented by pvDataJava and then calls the next method.
|
||||
@@ -349,20 +413,6 @@ public:
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
/** @brief Create a PvaClientArray.
|
||||
*
|
||||
* First call createRequest as implemented by pvDataJava and then call the next method.
|
||||
* @param request The syntax of request is defined by the copy facility of pvData.
|
||||
* @return The interface.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
PvaClientArrayPtr createArray(std::string const & request = "field(value)");
|
||||
/** @brief Create a PvaClientArray.
|
||||
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
|
||||
* @return The interface.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
PvaClientArrayPtr createArray(epics::pvData::PVStructurePtr const & pvRequest);
|
||||
/** @brief Create a PvaClientMonitor.
|
||||
*
|
||||
* Create and connect to a new PvaClientMonitor.
|
||||
@@ -373,7 +423,7 @@ public:
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
PvaClientMonitorPtr monitor(std::string const & request = "field(value,alarm,timeStamp)");
|
||||
/** @brief Call the next method with request = "field(value,alarm,timeStamp)"
|
||||
/** @brief Call the next method with request = "field(value,alarm,timeStamp)"
|
||||
*
|
||||
* @param pvaClientMonitorRequester The client callback.
|
||||
* @return The interface.
|
||||
@@ -462,7 +512,7 @@ private:
|
||||
std::string channelName;
|
||||
std::string providerName;
|
||||
ConnectState connectState;
|
||||
|
||||
|
||||
epics::pvData::CreateRequest::shared_pointer createRequest;
|
||||
PvaClientGetCachePtr pvaClientGetCache;
|
||||
PvaClientPutCachePtr pvaClientPutCache;
|
||||
@@ -484,19 +534,18 @@ public:
|
||||
friend class PvaClient;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that holds data returned by PvaClientGet or PvaClientPutGet
|
||||
/**
|
||||
* @brief A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientGetData.html">Overview of PvaClientGetData</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientGetData
|
||||
class epicsShareClass PvaClientData
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientGetData);
|
||||
POINTER_DEFINITIONS(PvaClientData);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientGetData() {}
|
||||
~PvaClientData() {}
|
||||
/** @brief Set a prefix for throw messages.
|
||||
*
|
||||
* This is called by other pvaClient classes.
|
||||
@@ -537,6 +586,7 @@ public:
|
||||
void setData(
|
||||
epics::pvData::PVStructurePtr const & pvStructureFrom,
|
||||
epics::pvData::BitSetPtr const & bitSetFrom);
|
||||
|
||||
/** @brief Is there a top level field named value.
|
||||
* @return The answer.
|
||||
*/
|
||||
@@ -603,6 +653,68 @@ public:
|
||||
* @return The timeStamp.
|
||||
*/
|
||||
epics::pvData::TimeStamp getTimeStamp();
|
||||
/** @brief parse from args
|
||||
*
|
||||
* Accepts arguments of the form json or field='value' where value is json syntax.
|
||||
* field is name.name...
|
||||
* @param args The arguments.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void parse(const std::vector<std::string> &args);
|
||||
/** @brief generate JSON output from the current PVStructure and displays it on the output stream.
|
||||
*
|
||||
* @param strm The output stream.
|
||||
* @param ignoreUnprintable false or true; The default is true.
|
||||
* @param multiline false or true; The default is false.
|
||||
*
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
void streamJSON(
|
||||
std::ostream& strm,
|
||||
bool ignoreUnprintable = true,
|
||||
bool multiLine = false);
|
||||
/** @brief set length of all array fields to 0
|
||||
*/
|
||||
void zeroArrayLength();
|
||||
protected:
|
||||
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||
PvaClientData(epics::pvData::StructureConstPtr const & structure);
|
||||
epics::pvData::PVFieldPtr getSinglePVField();
|
||||
void checkValue();
|
||||
std::string messagePrefix;
|
||||
private:
|
||||
void parse(
|
||||
const std::string &arg,
|
||||
const epics::pvData::PVFieldPtr &dest,
|
||||
epics::pvData::BitSetPtr &bitSet);
|
||||
void parse(
|
||||
const std::string &arg,
|
||||
const epics::pvData::PVUnionPtr &dest);
|
||||
void zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure);
|
||||
|
||||
epics::pvData::StructureConstPtr structure;
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::BitSetPtr bitSet;
|
||||
|
||||
epics::pvData::PVFieldPtr pvValue;
|
||||
epics::pvData::PVAlarm pvAlarm;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
friend class PvaClientGet;
|
||||
friend class PvaClientPutGet;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that holds data returned by PvaClientGet or PvaClientPutGet
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvaClientGetData : public PvaClientData
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientGetData);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientGetData() {}
|
||||
/** @brief Factory method for creating an instance of PvaClientGetData.
|
||||
*
|
||||
* NOTE: Not normally called by clients
|
||||
@@ -612,120 +724,23 @@ public:
|
||||
static PvaClientGetDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||
private:
|
||||
PvaClientGetData(epics::pvData::StructureConstPtr const & structure);
|
||||
void checkValue();
|
||||
epics::pvData::StructureConstPtr structure;
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::BitSetPtr bitSet;
|
||||
|
||||
std::string messagePrefix;
|
||||
epics::pvData::PVFieldPtr pvValue;
|
||||
epics::pvData::PVAlarm pvAlarm;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
friend class PvaClientGet;
|
||||
friend class PvaClientPutGet;
|
||||
};
|
||||
|
||||
class PvaClientPostHandlerPvt; // private to PvaClientPutData
|
||||
/**
|
||||
/**
|
||||
* @brief A class that holds data given to by PvaClientPut or PvaClientPutGet
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientPutData.html">Overview of PvaClientPutData</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientPutData
|
||||
class epicsShareClass PvaClientPutData : public PvaClientData
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientPutData);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
*/
|
||||
~PvaClientPutData() {}
|
||||
/** @brief Set a prefix for throw messages.
|
||||
*
|
||||
* @param value The prefix.
|
||||
*/
|
||||
void setMessagePrefix(std::string const & value);
|
||||
/** @brief Get the structure.
|
||||
*
|
||||
* @return The Structure
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::StructureConstPtr getStructure();
|
||||
/** @brief Get the pvStructure.
|
||||
*
|
||||
* @return the pvStructure.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::PVStructurePtr getPVStructure();
|
||||
/** @brief Get the changed BitSet for the pvStructure
|
||||
*
|
||||
* This shows which fields have changed values.
|
||||
* @return The bitSet
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::BitSetPtr getChangedBitSet();
|
||||
/** @brief Show the fields that have changed values.
|
||||
*
|
||||
* @param out The stream that shows the changed fields.
|
||||
* @return The stream that was passed as out.
|
||||
*/
|
||||
std::ostream & showChanged(std::ostream & out);
|
||||
/**
|
||||
* @brief Is there a top level field named value.
|
||||
*
|
||||
* @return The answer.
|
||||
*/
|
||||
bool hasValue();
|
||||
/** @brief Is the value field a scalar?
|
||||
*
|
||||
* @return The answer.
|
||||
*/
|
||||
bool isValueScalar();
|
||||
/** @brief Is the value field a scalar array?
|
||||
* @return The answer.
|
||||
*/
|
||||
bool isValueScalarArray();
|
||||
/** Get the interface to the value field.
|
||||
*
|
||||
* @return The interface. an excetion is thrown if a value field does not exist.
|
||||
*/
|
||||
epics::pvData::PVFieldPtr getValue();
|
||||
/** @brief Get the interface to a scalar value field.
|
||||
*
|
||||
* @return The interface for a scalar value field.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::PVScalarPtr getScalarValue();
|
||||
/** @brief Get the interface to an array value field.
|
||||
* @return The interface.
|
||||
* An exception is thown if no array value field.
|
||||
*/
|
||||
std::tr1::shared_ptr<epics::pvData::PVArray> getArrayValue();
|
||||
/** @brief Get the interface to a scalar array value field.
|
||||
* @return Return the interface.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
std::tr1::shared_ptr<epics::pvData::PVScalarArray> getScalarArrayValue();
|
||||
/** @brief Get the value as a double.
|
||||
*
|
||||
* If value is not a numeric scalar an exception is thrown.
|
||||
* @return The value.
|
||||
*/
|
||||
double getDouble();
|
||||
/** @brief Get the value as a string.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
std::string getString();
|
||||
/** @brief Get the value as a double array.
|
||||
* If the value is not a numeric array an exception is thrown.
|
||||
* @return The value.
|
||||
*/
|
||||
epics::pvData::shared_vector<const double> getDoubleArray();
|
||||
/** @brief Get the value as a string array.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::shared_vector<const std::string> getStringArray();
|
||||
/** @brief Put the value as a double.
|
||||
* @param value The new value.
|
||||
* An exception is also thrown if the actualy type can cause an overflow.
|
||||
@@ -759,55 +774,24 @@ public:
|
||||
static PvaClientPutDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||
private:
|
||||
PvaClientPutData(epics::pvData::StructureConstPtr const &structure);
|
||||
void checkValue();
|
||||
void postPut(size_t fieldNumber);
|
||||
|
||||
std::vector<epics::pvData::PostHandlerPtr> postHandler;
|
||||
epics::pvData::StructureConstPtr structure;
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::BitSetPtr bitSet;
|
||||
friend class PvaClientPostHandlerPvt;
|
||||
|
||||
std::string messagePrefix;
|
||||
epics::pvData::PVFieldPtr pvValue;
|
||||
friend class PvaClientPut;
|
||||
friend class PvaClientPutGet;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A class that holds data returned by PvaClientMonitor
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientMonitorData.html">Overview of PvaClientMonitorData</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientMonitorData
|
||||
class epicsShareClass PvaClientMonitorData : public PvaClientData
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMonitorData);
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
*/
|
||||
~PvaClientMonitorData() {}
|
||||
/** @brief Set a prefix for throw messages.
|
||||
* @param value The prefix.
|
||||
*/
|
||||
void setMessagePrefix(std::string const & value);
|
||||
/** @brief Get the structure.
|
||||
* @return The Structure
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::StructureConstPtr getStructure();
|
||||
/** @brief Get the pvStructure.
|
||||
* @return the pvStructure.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::PVStructurePtr getPVStructure();
|
||||
/** @brief Get the changed BitSet for the pvStructure,
|
||||
*
|
||||
* This shows which fields have changed value.
|
||||
* @return The bitSet
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::BitSetPtr getChangedBitSet();
|
||||
/** @brief Get the overrun BitSet for the pvStructure
|
||||
* This shows which fields have had more than one change.
|
||||
* @return The bitSet
|
||||
@@ -818,118 +802,27 @@ public:
|
||||
* @param out The stream that shows the changed fields.
|
||||
* @return The stream that was passed as out.
|
||||
*/
|
||||
std::ostream & showChanged(std::ostream & out);
|
||||
/** @brief Show the fields that have overrun.
|
||||
* @param out The stream that shows the overrun fields.
|
||||
* @return The stream that was passed as out
|
||||
*/
|
||||
std::ostream & showOverrun(std::ostream & out);
|
||||
/** @brief Is there a top level field named value.
|
||||
* @return The answer.
|
||||
*/
|
||||
bool hasValue();
|
||||
/** @brief Is the value field a scalar?
|
||||
* @return The answer.
|
||||
*/
|
||||
bool isValueScalar();
|
||||
/** @brief Is the value field a scalar array?
|
||||
* @return The answer.
|
||||
*/
|
||||
bool isValueScalarArray();
|
||||
/** @brief Get the interface to the value field.
|
||||
* @return The interface. an excetion is thrown if a value field does not exist.
|
||||
*/
|
||||
epics::pvData::PVFieldPtr getValue();
|
||||
/** @brief Get the interface to a scalar value field.
|
||||
* @return The interface for a scalar value field.
|
||||
* @throw runtime_error if failure.
|
||||
* An exception is thown if no scalar value field.
|
||||
*/
|
||||
epics::pvData::PVScalarPtr getScalarValue();
|
||||
/** @brief Get the interface to an array value field.
|
||||
* @return The interface.
|
||||
* @throw runtime_error if failure.
|
||||
* An exception is thown if no array value field.
|
||||
*/
|
||||
std::tr1::shared_ptr<epics::pvData::PVArray> getArrayValue();
|
||||
/** @brief Get the interface to a scalar array value field.
|
||||
* @return Return the interface.
|
||||
* @throw runtime_error if failure.
|
||||
* An exception is thown if no scalar array value field.
|
||||
*/
|
||||
std::tr1::shared_ptr<epics::pvData::PVScalarArray> getScalarArrayValue();
|
||||
/** @brief Get the value as a double.
|
||||
*
|
||||
* If value is not a numeric scalar an exception is thrown.
|
||||
* @return The value.
|
||||
*/
|
||||
double getDouble();
|
||||
/** @brief Get the value as a string.
|
||||
*
|
||||
* If value is not a scalar an exception is thrown
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
std::string getString();
|
||||
/** @brief Get the value as a double array.
|
||||
*
|
||||
* If the value is not a numeric array an exception is thrown.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::shared_vector<const double> getDoubleArray();
|
||||
/** @brief Get the value as a string array.
|
||||
*
|
||||
* If the value is not a string array an exception is thrown.
|
||||
* @return The value.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::shared_vector<const std::string> getStringArray();
|
||||
/** @brief Get the alarm.
|
||||
*
|
||||
* If the pvStructure as an alarm field it's values are returned.
|
||||
* If no then alarm shows that not alarm defined.
|
||||
* @return The alarm.
|
||||
* @throw runtime_error if failure.
|
||||
*/
|
||||
epics::pvData::Alarm getAlarm();
|
||||
/** @brief Get the timeStamp.
|
||||
*
|
||||
* If the pvStructure has a timeStamp field, it's values are returned.
|
||||
* If no then all fields are 0.
|
||||
* @return The timeStamp.
|
||||
*/
|
||||
epics::pvData::TimeStamp getTimeStamp();
|
||||
/** Factory method for creating an instance of PvaClientGetData.
|
||||
* NOTE: Not normally called by clients
|
||||
* @param structure Introspection interface
|
||||
*/
|
||||
static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||
/** Put data into PVStructure from monitorElement
|
||||
* NOTE: Not normally called by clients
|
||||
* @param monitorElement the monitorElement that has new data.
|
||||
*/
|
||||
void setData(epics::pvData::MonitorElementPtr const & monitorElement);
|
||||
/** Factory method for creating an instance of PvaClientGetData.
|
||||
* NOTE: Not normally called by clients
|
||||
* @param structure Introspection interface
|
||||
*/
|
||||
static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||
private:
|
||||
PvaClientMonitorData(epics::pvData::StructureConstPtr const & structure);
|
||||
void checkValue();
|
||||
|
||||
epics::pvData::StructureConstPtr structure;
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
epics::pvData::BitSetPtr changedBitSet;
|
||||
epics::pvData::BitSetPtr overrunBitSet;
|
||||
|
||||
std::string messagePrefix;
|
||||
epics::pvData::PVFieldPtr pvValue;
|
||||
epics::pvData::PVAlarm pvAlarm;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
friend class PvaClientMonitor;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientProcessRequester.html">Overview of PvaClientProcessRequester</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientProcessRequester
|
||||
{
|
||||
@@ -964,17 +857,15 @@ typedef std::tr1::shared_ptr<ChannelProcessRequesterImpl> ChannelProcessRequeste
|
||||
/**
|
||||
* @brief An easy to use alternative to ChannelProcess.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientProcess.html">Overview of PvaClientProcess</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientProcess :
|
||||
public PvaClientChannelStateChangeRequester,
|
||||
public std::tr1::enable_shared_from_this<PvaClientProcess>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientProcess);
|
||||
/** @brief Create a PvaClientProcess.
|
||||
* @param &pvaClient Interface to PvaClient
|
||||
* @param channel Interface to Channel
|
||||
* @param pvaClient Interface to PvaClient
|
||||
* @param pvaClientChannel Interface to Channel
|
||||
* @param pvRequest The request structure.
|
||||
* @return The interface to the PvaClientProcess.
|
||||
*/
|
||||
@@ -983,7 +874,7 @@ public:
|
||||
PvaClientChannelPtr const & pvaClientChannel,
|
||||
epics::pvData::PVStructurePtr const &pvRequest
|
||||
);
|
||||
|
||||
|
||||
/** @brief Destructor
|
||||
*/
|
||||
~PvaClientProcess();
|
||||
@@ -1037,7 +928,7 @@ private:
|
||||
PvaClientPtr const &pvaClient,
|
||||
PvaClientChannelPtr const & pvaClientChannel,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
|
||||
|
||||
void checkProcessState();
|
||||
enum ProcessConnectState {connectIdle,connectActive,connected};
|
||||
|
||||
@@ -1054,13 +945,11 @@ private:
|
||||
|
||||
ProcessConnectState connectState;
|
||||
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
|
||||
PvaClientProcessRequesterWPtr pvaClientProcessRequester;
|
||||
enum ProcessState {processIdle,processActive,processComplete};
|
||||
ProcessState processState;
|
||||
ChannelProcessRequesterImplPtr channelProcessRequester;
|
||||
public:
|
||||
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
|
||||
friend class ChannelProcessRequesterImpl;
|
||||
};
|
||||
|
||||
@@ -1072,7 +961,6 @@ typedef std::tr1::shared_ptr<ChannelGetRequesterImpl> ChannelGetRequesterImplPtr
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientGetRequester.html">Overview of PvaClientGetRequester</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientGetRequester
|
||||
{
|
||||
@@ -1101,10 +989,8 @@ public:
|
||||
/**
|
||||
* @brief An easy to use alternative to ChannelGet.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientGet.html">Overview of PvaClientGet</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientGet :
|
||||
public PvaClientChannelStateChangeRequester,
|
||||
public std::tr1::enable_shared_from_this<PvaClientGet>
|
||||
{
|
||||
public:
|
||||
@@ -1183,7 +1069,7 @@ private:
|
||||
PvaClientChannelPtr const & pvaClientChannel,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
|
||||
void checkGetState();
|
||||
void checkConnectState();
|
||||
enum GetConnectState {connectIdle,connectActive,connected};
|
||||
|
||||
PvaClient::weak_pointer pvaClient;
|
||||
@@ -1200,14 +1086,12 @@ private:
|
||||
|
||||
GetConnectState connectState;
|
||||
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
|
||||
PvaClientGetRequesterWPtr pvaClientGetRequester;
|
||||
|
||||
enum GetState {getIdle,getActive,getComplete};
|
||||
GetState getState;
|
||||
ChannelGetRequesterImplPtr channelGetRequester;
|
||||
public:
|
||||
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
|
||||
friend class ChannelGetRequesterImpl;
|
||||
};
|
||||
|
||||
@@ -1220,7 +1104,6 @@ typedef std::tr1::shared_ptr<ChannelPutRequesterImpl> ChannelPutRequesterImplPtr
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientPutRequester.html">Overview of PvaClientPutRequester</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientPutRequester
|
||||
{
|
||||
@@ -1260,17 +1143,15 @@ public:
|
||||
/**
|
||||
* @brief An easy to use alternative to ChannelPut.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientPut.html">Overview of PvaClientPut</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientPut :
|
||||
public PvaClientChannelStateChangeRequester,
|
||||
public std::tr1::enable_shared_from_this<PvaClientPut>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientPut);
|
||||
/** @brief Create a PvaClientPut.
|
||||
* @param &pvaClient Interface to PvaClient
|
||||
* @param channel Interface to Channel
|
||||
* @param pvaClient Interface to PvaClient
|
||||
* @param pvaClientChannel Interface to Channel
|
||||
* @param pvRequest The request structure.
|
||||
* @return The interface to the PvaClientPut.
|
||||
*/
|
||||
@@ -1354,8 +1235,8 @@ private :
|
||||
PvaClientPtr const &pvaClient,
|
||||
PvaClientChannelPtr const & pvaClientChannel,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
|
||||
void checkPutState();
|
||||
|
||||
void checkConnectState();
|
||||
enum PutConnectState {connectIdle,connectActive,connected};
|
||||
|
||||
PvaClient::weak_pointer pvaClient;
|
||||
@@ -1374,10 +1255,8 @@ private :
|
||||
enum PutState {putIdle,getActive,putActive,putComplete};
|
||||
PutState putState;
|
||||
ChannelPutRequesterImplPtr channelPutRequester;
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
|
||||
PvaClientPutRequesterWPtr pvaClientPutRequester;
|
||||
public:
|
||||
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
|
||||
friend class ChannelPutRequesterImpl;
|
||||
};
|
||||
|
||||
@@ -1389,7 +1268,6 @@ typedef std::tr1::shared_ptr<ChannelPutGetRequesterImpl> ChannelPutGetRequesterI
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientPutGetRequester.html">Overview of PvaClientPutGetRequester</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientPutGetRequester
|
||||
{
|
||||
@@ -1434,24 +1312,22 @@ public:
|
||||
PvaClientPutGetPtr const & clientPutGet)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief An easy to use alternative to ChannelPutGet.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientPutGet.html">Overview of PvaClientPutGet</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientPutGet :
|
||||
public PvaClientChannelStateChangeRequester,
|
||||
public std::tr1::enable_shared_from_this<PvaClientPutGet>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientPutGet);
|
||||
/** @brief Create a PvaClientPutGet.
|
||||
* @param &pvaClient Interface to PvaClient
|
||||
* @param channel Interface to Channel
|
||||
* @param pvaClient Interface to PvaClient
|
||||
* @param pvaClientChannel Interface to Channel
|
||||
* @param pvRequest The request structure.
|
||||
* @return The interface to the PvaClientPutGet.
|
||||
*/
|
||||
@@ -1526,11 +1402,11 @@ public:
|
||||
/** @brief Get the put data.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientPutDataPtr getPutData();
|
||||
PvaClientPutDataPtr getPutData();
|
||||
/** @brief Get the get data.
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientGetDataPtr getGetData();
|
||||
PvaClientGetDataPtr getGetData();
|
||||
/** @brief Get the PvaClientChannel;
|
||||
*
|
||||
* @return The interface.
|
||||
@@ -1584,18 +1460,14 @@ private :
|
||||
enum PutGetState {putGetIdle,putGetActive,putGetComplete};
|
||||
PutGetState putGetState;
|
||||
ChannelPutGetRequesterImplPtr channelPutGetRequester;
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
|
||||
PvaClientPutGetRequesterWPtr pvaClientPutGetRequester;
|
||||
public:
|
||||
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
|
||||
friend class ChannelPutGetRequesterImpl;
|
||||
};
|
||||
|
||||
//class ChannelMonitorRequester; // private to PvaClientMonitor
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientMonitorRequester.html">Overview of PvaClientMonitorRequester</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientMonitorRequester
|
||||
{
|
||||
@@ -1636,10 +1508,9 @@ typedef std::tr1::shared_ptr<MonitorRequesterImpl> MonitorRequesterImplPtr;
|
||||
/**
|
||||
* @brief An easy to use alternative to Monitor.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientMonitor.html">Overview of PvaClientMonitor</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientMonitor :
|
||||
public PvaClientChannelStateChangeRequester,
|
||||
public PvaClientChannelStateChangeRequester, // remove when deprecated create removed
|
||||
public PvaClientMonitorRequester,
|
||||
public std::tr1::enable_shared_from_this<PvaClientMonitor>
|
||||
{
|
||||
@@ -1664,6 +1535,7 @@ public:
|
||||
* @param stateChangeRequester The state change requester. Can be null.
|
||||
* @param monitorRequester The monitor requester. Can be null;
|
||||
* @return The new instance.
|
||||
* @deprecated client can create PvaClientMonitor on first channel connect.
|
||||
*/
|
||||
static PvaClientMonitorPtr create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
@@ -1672,9 +1544,9 @@ public:
|
||||
std::string const & request,
|
||||
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester
|
||||
= PvaClientChannelStateChangeRequesterPtr(),
|
||||
PvaClientMonitorRequesterPtr const & monitorRequester
|
||||
PvaClientMonitorRequesterPtr const & monitorRequester
|
||||
= PvaClientMonitorRequesterPtr()
|
||||
);
|
||||
) EPICS_DEPRECATED;
|
||||
/** @brief Destructor
|
||||
*/
|
||||
~PvaClientMonitor();
|
||||
@@ -1735,7 +1607,7 @@ public:
|
||||
*
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMonitorDataPtr getData();
|
||||
PvaClientMonitorDataPtr getData();
|
||||
private:
|
||||
std::string getRequesterName();
|
||||
void message(std::string const & message,epics::pvData::MessageType messageType);
|
||||
@@ -1766,16 +1638,15 @@ private:
|
||||
epics::pvData::Status monitorConnectStatus;
|
||||
epics::pvData::MonitorPtr monitor;
|
||||
epics::pvData::MonitorElementPtr monitorElement;
|
||||
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
|
||||
|
||||
PvaClientMonitorRequesterWPtr pvaClientMonitorRequester;
|
||||
MonitorConnectState connectState;
|
||||
bool userPoll;
|
||||
bool userWait;
|
||||
MonitorRequesterImplPtr monitorRequester;
|
||||
|
||||
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester; //deprecate
|
||||
public:
|
||||
void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected);
|
||||
void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected); //deprecate
|
||||
void event(PvaClientMonitorPtr const & monitor);
|
||||
friend class MonitorRequesterImpl;
|
||||
};
|
||||
@@ -1785,7 +1656,6 @@ public:
|
||||
/**
|
||||
* @brief Optional client callback.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientRPCRequester.html">Overview of PvaClientRPCRequester</a>
|
||||
*/
|
||||
class PvaClientRPCRequester
|
||||
{
|
||||
@@ -1811,7 +1681,6 @@ typedef std::tr1::shared_ptr<RPCRequesterImpl> RPCRequesterImplPtr;
|
||||
/**
|
||||
* @brief An easy to use alternative to RPC.
|
||||
*
|
||||
* <a href = "../htmldoxygen/pvaClientRPC.html">Overview of PvaClientRPC</a>
|
||||
*/
|
||||
class epicsShareClass PvaClientRPC :
|
||||
public std::tr1::enable_shared_from_this<PvaClientRPC>
|
||||
@@ -1844,7 +1713,7 @@ public:
|
||||
* @brief Set a timeout for a request.
|
||||
* @param responseTimeout The time in seconds to wait for a request to complete.
|
||||
*/
|
||||
void setResponseTimeout(double responseTimeout)
|
||||
void setResponseTimeout(double responseTimeout)
|
||||
{
|
||||
this->responseTimeout = responseTimeout;
|
||||
}
|
||||
@@ -1914,18 +1783,19 @@ private:
|
||||
PvaClient::weak_pointer pvaClient;
|
||||
epics::pvAccess::Channel::weak_pointer channel;
|
||||
epics::pvData::PVStructurePtr pvRequest;
|
||||
|
||||
|
||||
epics::pvData::Mutex mutex;
|
||||
epics::pvData::Event waitForConnect;
|
||||
epics::pvData::Event waitForDone;
|
||||
|
||||
PvaClientRPCRequesterWPtr pvaClientRPCRequester;
|
||||
PvaClientRPCRequesterWPtr pvaClientRPCRequester;
|
||||
RPCRequesterImplPtr rpcRequester;
|
||||
epics::pvAccess::ChannelRPC::shared_pointer channelRPC;
|
||||
epics::pvData::PVStructurePtr pvResponse;
|
||||
|
||||
enum RPCState {rpcIdle,rpcActive,rpcComplete};
|
||||
RPCState rpcState;
|
||||
epics::pvData::Status requestStatus;
|
||||
double responseTimeout;
|
||||
friend class RPCRequesterImpl;
|
||||
};
|
||||
@@ -1933,10 +1803,3 @@ private:
|
||||
}}
|
||||
|
||||
#endif /* PVACLIENT_H */
|
||||
|
||||
/** @page Overview Documentation
|
||||
*
|
||||
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+84
-137
@@ -21,14 +21,14 @@
|
||||
|
||||
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||
# undef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
class PvaClientMultiChannel;
|
||||
@@ -66,14 +66,19 @@ public:
|
||||
* @param pvaClient The interface to pvaClient.
|
||||
* @param channelNames The names of the channel..
|
||||
* @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 providerNames The providerName for each Channells
|
||||
* @return The interface to the PvaClientMultiChannel
|
||||
*/
|
||||
static PvaClientMultiChannelPtr create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const std::string> const & channelNames,
|
||||
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>()
|
||||
);
|
||||
/**
|
||||
* @brief Destructor
|
||||
@@ -115,7 +120,7 @@ public:
|
||||
* @brief create a pvaClientMultiGetDouble
|
||||
* @return The interface.
|
||||
*/
|
||||
PvaClientMultiGetDoublePtr createGet();
|
||||
PvaClientMultiGetDoublePtr createGet();
|
||||
/**
|
||||
* @brief Create a pvaClientMultiPutDouble.
|
||||
* @return The interface.
|
||||
@@ -148,20 +153,24 @@ public:
|
||||
private:
|
||||
PvaClientMultiChannel(
|
||||
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,
|
||||
size_t maxNotConnected);
|
||||
size_t maxNotConnected,
|
||||
epics::pvData::shared_vector<const std::string> const & providerNames);
|
||||
void checkConnected();
|
||||
|
||||
|
||||
PvaClientPtr pvaClient;
|
||||
epics::pvData::shared_vector<const std::string> channelName;
|
||||
epics::pvData::shared_vector<const std::string> channelNames;
|
||||
std::string providerName;
|
||||
size_t maxNotConnected;
|
||||
epics::pvData::shared_vector<const std::string> const & providerNames;
|
||||
|
||||
size_t numChannel;
|
||||
size_t numProviderNames;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
size_t numConnected;
|
||||
bool firstConnect;
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
|
||||
epics::pvData::CreateRequest::shared_pointer createRequest;
|
||||
@@ -176,19 +185,16 @@ class epicsShareClass PvaClientMultiGetDouble :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
|
||||
|
||||
/**
|
||||
* @brief Create a PvaClientMultiGetDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientMultiGetDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientMultiGetDouble();
|
||||
|
||||
/**
|
||||
* @brief Create a channelGet for each channel.
|
||||
*/
|
||||
@@ -198,13 +204,6 @@ public:
|
||||
* @return The double[] where each element is the value field of the corresponding channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<double> get();
|
||||
/** @brief Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiGetDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
private:
|
||||
PvaClientMultiGetDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
@@ -214,7 +213,7 @@ private:
|
||||
PvaClientChannelArray pvaClientChannelArray;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
|
||||
epics::pvData::shared_vector<double> doubleValue;
|
||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||
bool isGetConnected;
|
||||
@@ -229,15 +228,15 @@ class epicsShareClass PvaClientMultiPutDouble :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
|
||||
|
||||
/** @brief Create a PvaClientMultiPutDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientMultiPutDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientMultiPutDouble();
|
||||
/**
|
||||
* @brief Create a channelPut for each channel.
|
||||
@@ -247,13 +246,7 @@ public:
|
||||
* @param data The array of data for each channel.
|
||||
*/
|
||||
void put(epics::pvData::shared_vector<double> const &data);
|
||||
/** @brief Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiPutDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
PvaClientMultiPutDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
@@ -277,15 +270,15 @@ class epicsShareClass PvaClientMultiMonitorDouble :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
|
||||
|
||||
/** @brief Create a PvaClientMultiMonitorDouble.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientMultiMonitorDoublePtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientMultiMonitorDouble();
|
||||
/**
|
||||
* @brief Connect a channel monitor for each channel.
|
||||
@@ -310,13 +303,7 @@ public:
|
||||
* @return The double[] where each element is the value field of the corresponding channel.
|
||||
*/
|
||||
epics::pvData::shared_vector<double> get();
|
||||
/** @brief Monitor the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientMultiMonitorDoublePtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
PvaClientMultiMonitorDouble(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
@@ -341,18 +328,16 @@ class epicsShareClass PvaClientNTMultiGet :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientNTMultiGet);
|
||||
/**
|
||||
* @brief Create a PvaClientNTMultiGet.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @param pvRequest The pvRequest for each channel.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientNTMultiGetPtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientNTMultiGet();
|
||||
/**
|
||||
* @brief Connect a channelGet for each channel.
|
||||
@@ -360,20 +345,16 @@ public:
|
||||
void connect();
|
||||
/**
|
||||
* @brief Get each channel.
|
||||
*
|
||||
* @param valueOnly use only value for union.
|
||||
*/
|
||||
void get();
|
||||
void get(bool valueOnly = true);
|
||||
/**
|
||||
* @brief Get the data from the last get.
|
||||
* @return the pvaClientNTMultiData.
|
||||
*/
|
||||
PvaClientNTMultiDataPtr getData();
|
||||
/** @brief Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientNTMultiGetPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
PvaClientNTMultiGet(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
@@ -386,8 +367,7 @@ private:
|
||||
epics::pvData::PVStructurePtr pvRequest;
|
||||
size_t nchannel;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
|
||||
|
||||
PvaClientNTMultiDataPtr pvaClientNTMultiData;
|
||||
std::vector<PvaClientGetPtr> pvaClientGet;
|
||||
bool isConnected;
|
||||
@@ -402,16 +382,15 @@ class epicsShareClass PvaClientNTMultiPut :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientNTMultiPut);
|
||||
/**
|
||||
* @brief Create a PvaClientNTMultiPut.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientNTMultiPutPtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray);
|
||||
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientNTMultiPut();
|
||||
/**
|
||||
* @brief Connect a channelPut for each channel.
|
||||
@@ -424,15 +403,9 @@ public:
|
||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
|
||||
/**
|
||||
* @brief Issue a put for each channel.
|
||||
' */
|
||||
void put();
|
||||
/** @brief Get the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientNTMultiPutPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
void put();
|
||||
|
||||
private:
|
||||
PvaClientNTMultiPut(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
@@ -458,16 +431,16 @@ class epicsShareClass PvaClientNTMultiMonitor :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
|
||||
/** @brief Create a PvaClientNTMultiMonitor.
|
||||
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
|
||||
* @param pvaClientChannelArray The PvaClientChannel array.
|
||||
* @param pvRequest The pvRequest for each channel.
|
||||
* @return The interface.
|
||||
*/
|
||||
protected:
|
||||
static PvaClientNTMultiMonitorPtr create(
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
friend class PvaClientMultiChannel;
|
||||
public:
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~PvaClientNTMultiMonitor();
|
||||
/**
|
||||
* @brief Connect to a channel monitor for each channel.
|
||||
@@ -476,10 +449,11 @@ public:
|
||||
/**
|
||||
* @brief Poll each channel.
|
||||
*
|
||||
* @param valueOnly use only value for union.
|
||||
* If any has new data it is used to update the double[].
|
||||
* @return (false,true) if (no, at least one) value was updated.
|
||||
*/
|
||||
bool poll();
|
||||
bool poll(bool valueOnly = true);
|
||||
/**
|
||||
* @brief Wait until poll returns true.
|
||||
* @param secondsToWait The time to keep trying.
|
||||
@@ -492,13 +466,7 @@ public:
|
||||
* @return the pvaClientNTMultiData.
|
||||
*/
|
||||
PvaClientNTMultiDataPtr getData();
|
||||
/** Monitor the shared pointer to self.
|
||||
* @return The shared pointer.
|
||||
*/
|
||||
PvaClientNTMultiMonitorPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
private:
|
||||
PvaClientNTMultiMonitor(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
@@ -525,61 +493,43 @@ class epicsShareClass PvaClientNTMultiData :
|
||||
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvaClientNTMultiData);
|
||||
/**
|
||||
* @brief Create 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 &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
~PvaClientNTMultiData();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get the number of channels.
|
||||
* @return The number of channels.
|
||||
*/
|
||||
size_t getNumber();
|
||||
|
||||
/**
|
||||
* @brief Set the timeStamp base for computing deltaTimes.
|
||||
*/
|
||||
void startDeltaTime();
|
||||
|
||||
/**
|
||||
* @brief Update NTMultiChannel fields.
|
||||
*/
|
||||
void endDeltaTime();
|
||||
/**
|
||||
/**
|
||||
* @brief Get the time when the last get was made.
|
||||
* @return The timeStamp.
|
||||
*/
|
||||
epics::pvData::TimeStamp getTimeStamp();
|
||||
epics::pvData::TimeStamp getTimeStamp();
|
||||
/**
|
||||
* @brief Get the NTMultiChannel.
|
||||
* @return The value.
|
||||
*/
|
||||
epics::nt::NTMultiChannelPtr getNTMultiChannel();
|
||||
/** @brief 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()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> getChannelChangeFlags();
|
||||
protected:
|
||||
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:
|
||||
PvaClientNTMultiData(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest);
|
||||
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
|
||||
void setPVStructure(
|
||||
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
||||
|
||||
@@ -592,6 +542,7 @@ private:
|
||||
bool gotAlarm;
|
||||
bool gotTimeStamp;
|
||||
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> changeFlags;
|
||||
epics::pvData::StructureConstPtr ntMultiChannelStructure;
|
||||
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
|
||||
epics::pvData::shared_vector<epics::pvData::int32> severity;
|
||||
@@ -603,13 +554,9 @@ private:
|
||||
epics::pvData::Alarm alarm;
|
||||
epics::pvData::TimeStamp timeStamp;;
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
friend class PvaClientNTMultiGet;
|
||||
friend class PvaClientNTMultiPut;
|
||||
friend class PvaClientNTMultiMonitor;
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||
|
||||
|
||||
+6
-7
@@ -18,13 +18,12 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvAccess::ca;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
class epicsShareClass PvaClientChannelCache
|
||||
@@ -43,7 +42,7 @@ public:
|
||||
private:
|
||||
map<string,PvaClientChannelPtr> pvaClientChannelMap;
|
||||
};
|
||||
|
||||
|
||||
PvaClientChannelPtr PvaClientChannelCache::getChannel(
|
||||
string const & channelName,
|
||||
string const & providerName)
|
||||
@@ -78,7 +77,7 @@ void PvaClientChannelCache::showCache()
|
||||
string providerName = channel->getProvider()->getProviderName();
|
||||
cout << "channel " << channelName << " provider " << providerName << endl;
|
||||
pvaChannel->showCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t PvaClientChannelCache::cacheSize()
|
||||
@@ -111,6 +110,7 @@ PvaClientPtr PvaClient::get(std::string const & providerNames)
|
||||
return master;
|
||||
}
|
||||
|
||||
PvaClientPtr PvaClient::create() {return get();}
|
||||
|
||||
PvaClient::PvaClient(std::string const & providerNames)
|
||||
: pvaClientChannelCache(new PvaClientChannelCache()),
|
||||
@@ -137,7 +137,7 @@ PvaClient::PvaClient(std::string const & providerNames)
|
||||
}
|
||||
CAClientFactory::start();
|
||||
caStarted = true;
|
||||
} else {
|
||||
} else {
|
||||
if(!channelRegistry->getProvider(providerName)) {
|
||||
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
|
||||
}
|
||||
@@ -191,7 +191,7 @@ PvaClientChannelPtr PvaClient::channel(
|
||||
std::string const & providerName,
|
||||
double timeOut)
|
||||
{
|
||||
PvaClientChannelPtr pvaClientChannel =
|
||||
PvaClientChannelPtr pvaClientChannel =
|
||||
pvaClientChannelCache->getChannel(channelName,providerName);
|
||||
if(pvaClientChannel) return pvaClientChannel;
|
||||
pvaClientChannel = createChannel(channelName,providerName);
|
||||
@@ -231,4 +231,3 @@ size_t PvaClient::cacheSize()
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
+70
-44
@@ -18,7 +18,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -170,6 +169,7 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
|
||||
<< endl;
|
||||
}
|
||||
Lock xx(mutex);
|
||||
this->channel = channel;
|
||||
if(connectState==connected) return;
|
||||
if(connectState!=connectActive) {
|
||||
string message("PvaClientChannel::channelCreated");
|
||||
@@ -179,13 +179,10 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
|
||||
}
|
||||
if(!status.isOK()) {
|
||||
string message("PvaClientChannel::channelCreated");
|
||||
message += " channel " + channelName
|
||||
+ " status " + status.getMessage() + " why??";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(channel->isConnected()) {
|
||||
connectState = connected;
|
||||
waitForConnect.signal();
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientChannel::channelStateChange(
|
||||
@@ -198,15 +195,14 @@ void PvaClientChannel::channelStateChange(
|
||||
<< " " << Channel::ConnectionStateNames[connectionState]
|
||||
<< endl;
|
||||
}
|
||||
|
||||
bool waitingForConnect = false;
|
||||
if(connectState==connectActive) waitingForConnect = true;
|
||||
if(connectionState!=Channel::CONNECTED) {
|
||||
string mess(channelName +
|
||||
" connection state " + Channel::ConnectionStateNames[connectionState]);
|
||||
message(mess,errorMessage);
|
||||
Lock xx(mutex);
|
||||
connectState = notConnected;
|
||||
} else {
|
||||
Lock xx(mutex);
|
||||
this->channel = channel;
|
||||
connectState = connected;
|
||||
}
|
||||
if(waitingForConnect) {
|
||||
@@ -265,7 +261,7 @@ void PvaClientChannel::connect(double timeout)
|
||||
Status status = waitConnect(timeout);
|
||||
if(status.isOK()) return;
|
||||
if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::connect " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -317,18 +313,11 @@ Status PvaClientChannel::waitConnect(double timeout)
|
||||
return Status(Status::STATUSTYPE_ERROR," not connected");
|
||||
}
|
||||
|
||||
|
||||
PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
|
||||
{
|
||||
if(connectState!=connected) connect(5.0);
|
||||
throw std::runtime_error("PvaClientChannel::createField not implemented");
|
||||
}
|
||||
|
||||
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::createProcess invalid pvRequest: "
|
||||
+ createRequest->getMessage();
|
||||
throw std::runtime_error(message);
|
||||
@@ -362,7 +351,7 @@ PvaClientGetPtr PvaClientChannel::createGet(string const & request)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::createGet invalid pvRequest: "
|
||||
+ createRequest->getMessage();
|
||||
throw std::runtime_error(message);
|
||||
@@ -378,6 +367,26 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & 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(string const & request)
|
||||
{
|
||||
@@ -397,7 +406,7 @@ PvaClientPutPtr PvaClientChannel::createPut(string const & request)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::createPut invalid pvRequest: "
|
||||
+ createRequest->getMessage();
|
||||
throw std::runtime_error(message);
|
||||
@@ -413,11 +422,49 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
|
||||
return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
|
||||
}
|
||||
|
||||
void PvaClientChannel::putDouble(double value,string const & request)
|
||||
{
|
||||
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)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::createPutGet invalid pvRequest: "
|
||||
+ createRequest->getMessage();
|
||||
throw std::runtime_error(message);
|
||||
@@ -433,27 +480,6 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
|
||||
return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PvaClientArrayPtr PvaClientChannel::createArray(string const & request)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
+ " 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(string const & request)
|
||||
{
|
||||
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
|
||||
@@ -481,7 +507,7 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
|
||||
{
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
if(!pvRequest) {
|
||||
string message = string("channel ") + channelName
|
||||
string message = string("channel ") + channelName
|
||||
+ " PvaClientChannel::createMonitor invalid pvRequest: "
|
||||
+ createRequest->getMessage();
|
||||
throw std::runtime_error(message);
|
||||
@@ -501,7 +527,7 @@ PVStructurePtr PvaClientChannel::rpc(
|
||||
PVStructurePtr const & pvRequest,
|
||||
PVStructurePtr const & pvArgument)
|
||||
{
|
||||
|
||||
|
||||
PvaClientRPCPtr rpc = createRPC(pvRequest);
|
||||
return rpc->request(pvArgument);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
+42
-111
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -43,7 +42,7 @@ public:
|
||||
return clientGet->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||
if(!clientGet) return;
|
||||
clientGet->message(message,messageType);
|
||||
@@ -56,7 +55,7 @@ public:
|
||||
{
|
||||
PvaClientGetPtr clientGet(pvaClientGet.lock());
|
||||
if(!clientGet) return;
|
||||
clientGet->channelGetConnect(status,channelGet,structure);
|
||||
clientGet->channelGetConnect(status,channelGet,structure);
|
||||
}
|
||||
|
||||
virtual void getDone(
|
||||
@@ -99,50 +98,29 @@ PvaClientGet::PvaClientGet(
|
||||
getState(getIdle)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::PvaClientGet::PvaClientGet"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::PvaClientGet channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
PvaClientGet::~PvaClientGet()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientGet::~PvaClientGet"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout<< "PvaClientGet::~PvaClientGet channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientGet::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientGet::channelStateChange"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " isConnected " << (isConnected ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
if(isConnected&&!channelGet)
|
||||
{
|
||||
connectState = connectActive;
|
||||
channelGet = pvaClientChannel->getChannel()->createChannelGet(channelGetRequester,pvRequest);
|
||||
}
|
||||
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
|
||||
if(req) {
|
||||
req->channelStateChange(pvaClientChannel,isConnected);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientGet::checkGetState()
|
||||
void PvaClientGet::checkConnectState()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::checkGetState"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::checkConnectState channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
if(!pvaClientChannel->getChannel()->isConnected()) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientGet::checkGetState channel not connected ";
|
||||
+ " PvaClientGet::checkConnectState channel not connected ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(connectState==connectIdle) {
|
||||
@@ -156,19 +134,14 @@ void PvaClientGet::checkGetState()
|
||||
}
|
||||
}
|
||||
|
||||
// from ChannelGetRequester
|
||||
string PvaClientGet::getRequesterName()
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return string("PvaClientGet::getRequesterName PvaClient isDestroyed");
|
||||
return yyy->getRequesterName();
|
||||
return pvaClientChannel->getRequesterName();
|
||||
}
|
||||
|
||||
void PvaClientGet::message(string const & message,MessageType messageType)
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return;
|
||||
yyy->message(message, messageType);
|
||||
pvaClientChannel->message(message,messageType);
|
||||
}
|
||||
|
||||
void PvaClientGet::channelGetConnect(
|
||||
@@ -177,34 +150,26 @@ void PvaClientGet::channelGetConnect(
|
||||
StructureConstPtr const & structure)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::channelGetConnect"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
cout << "PvaClientGet::channelGetConnect channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
<< "\n";
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
this->channelGet = channelGet;
|
||||
channelGetConnectStatus = status;
|
||||
if(status.isOK()) {
|
||||
channelGetConnectStatus = status;
|
||||
this->channelGet = channelGet;
|
||||
connectState = connected;
|
||||
pvaClientData = PvaClientGetData::create(structure);
|
||||
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << pvRequest;
|
||||
string message = string("\nPvaClientGet::channelGetConnect)")
|
||||
+ "\npvRequest\n" + ss.str()
|
||||
+ "\nerror\n" + status.getMessage();
|
||||
channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
}
|
||||
waitForConnect.signal();
|
||||
}
|
||||
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
|
||||
if(req) {
|
||||
req->channelGetConnect(status,shared_from_this());
|
||||
}
|
||||
waitForConnect.signal();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientGet::getDone(
|
||||
@@ -214,32 +179,31 @@ void PvaClientGet::getDone(
|
||||
BitSetPtr const & bitSet)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::getDone"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
cout << "PvaClientGet::getDone channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
<< "\n";
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
channelGetStatus = status;
|
||||
getState = getComplete;
|
||||
if(status.isOK()) {
|
||||
pvaClientData->setData(pvStructure,bitSet);
|
||||
}
|
||||
getState = getComplete;
|
||||
waitForGet.signal();
|
||||
}
|
||||
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
|
||||
if(req) {
|
||||
req->getDone(status,shared_from_this());
|
||||
}
|
||||
waitForGet.signal();
|
||||
}
|
||||
|
||||
void PvaClientGet::connect()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::connect"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::connect channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
issueConnect();
|
||||
Status status = waitConnect();
|
||||
@@ -252,9 +216,8 @@ void PvaClientGet::connect()
|
||||
void PvaClientGet::issueConnect()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::issueConnect"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::issueConnect channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
if(connectState!=connectIdle) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
@@ -269,33 +232,18 @@ void PvaClientGet::issueConnect()
|
||||
Status PvaClientGet::waitConnect()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::waitConnect"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(connectState==connected) {
|
||||
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelGetConnectStatus;
|
||||
}
|
||||
if(connectState!=connectActive) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientGet::waitConnect illegal connect state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
cout << "PvaClientGet::waitConnect channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
waitForConnect.wait();
|
||||
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelGetConnectStatus;
|
||||
}
|
||||
|
||||
void PvaClientGet::get()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::get"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::get channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
issueGet();
|
||||
Status status = waitGet();
|
||||
@@ -308,9 +256,8 @@ void PvaClientGet::get()
|
||||
void PvaClientGet::issueGet()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::issueGet"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::issueGet channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
if(connectState==connectIdle) connect();
|
||||
if(getState==getActive) {
|
||||
@@ -325,34 +272,19 @@ void PvaClientGet::issueGet()
|
||||
Status PvaClientGet::waitGet()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::waitGet"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(getState==getComplete) {
|
||||
getState = getIdle;
|
||||
return channelGetStatus;
|
||||
}
|
||||
if(getState!=getActive){
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientGet::waitGet llegal get state";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
cout << "PvaClientGet::waitGet channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
waitForGet.wait();
|
||||
getState = getComplete;
|
||||
return channelGetStatus;
|
||||
}
|
||||
PvaClientGetDataPtr PvaClientGet::getData()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientGet::getData"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout<< "PvaClientGet::getData channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
checkGetState();
|
||||
checkConnectState();
|
||||
if(getState==getIdle) get();
|
||||
return pvaClientData;
|
||||
}
|
||||
@@ -360,9 +292,8 @@ PvaClientGetDataPtr PvaClientGet::getData()
|
||||
void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGet::setRequester"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
cout << "PvaClientGet::setRequester channelName "
|
||||
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
|
||||
}
|
||||
this->pvaClientGetRequester = pvaClientGetRequester;
|
||||
}
|
||||
|
||||
+3
-203
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -27,214 +26,15 @@ 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 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)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGetData::create"
|
||||
<< endl;
|
||||
}
|
||||
if(PvaClient::getDebug()) cout << "PvaClientGetData::create\n";
|
||||
PvaClientGetDataPtr epv(new PvaClientGetData(structure));
|
||||
return epv;
|
||||
}
|
||||
|
||||
PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure)
|
||||
: structure(structure),
|
||||
pvStructure(getPVDataCreate()->createPVStructure(structure)),
|
||||
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
|
||||
{
|
||||
messagePrefix = "";
|
||||
pvValue = pvStructure->getSubField("value");
|
||||
}
|
||||
|
||||
void PvaClientGetData::checkValue()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGetData::checkValue"
|
||||
<< endl;
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientGetData::setData"
|
||||
<< endl;
|
||||
}
|
||||
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);
|
||||
}
|
||||
: PvaClientData(structure)
|
||||
{}
|
||||
|
||||
}}
|
||||
|
||||
+30
-56
@@ -17,8 +17,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -46,7 +44,7 @@ public:
|
||||
return clientMonitor->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||
if(!clientMonitor) return;
|
||||
clientMonitor->message(message,messageType);
|
||||
@@ -59,21 +57,21 @@ public:
|
||||
{
|
||||
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||
if(!clientMonitor) return;
|
||||
clientMonitor->monitorConnect(status,monitor,structure);
|
||||
clientMonitor->monitorConnect(status,monitor,structure);
|
||||
}
|
||||
|
||||
virtual void unlisten(epics::pvData::MonitorPtr const & monitor)
|
||||
virtual void unlisten(MonitorPtr const & monitor)
|
||||
{
|
||||
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||
if(!clientMonitor) return;
|
||||
clientMonitor->unlisten(monitor);
|
||||
clientMonitor->unlisten(monitor);
|
||||
}
|
||||
|
||||
virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor)
|
||||
virtual void monitorEvent(MonitorPtr const & monitor)
|
||||
{
|
||||
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
|
||||
if(!clientMonitor) return;
|
||||
clientMonitor->monitorEvent(monitor);
|
||||
clientMonitor->monitorEvent(monitor);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -83,11 +81,6 @@ PvaClientMonitorPtr PvaClientMonitor::create(
|
||||
PvaClientChannelPtr const & pvaClientChannel,
|
||||
PVStructurePtr const &pvRequest)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientMonitor::create(pvaClient,pvaClientChannel,pvRequest)\n"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
|
||||
clientMonitor->monitorRequester = MonitorRequesterImplPtr(
|
||||
new MonitorRequesterImpl(clientMonitor,pvaClient));
|
||||
@@ -137,7 +130,9 @@ PvaClientMonitor::PvaClientMonitor(
|
||||
userWait(false)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientMonitor::PvaClientMonitor()" << endl;
|
||||
cout<< "PvaClientMonitor::PvaClientMonitor\n"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +169,11 @@ void PvaClientMonitor::channelStateChange(PvaClientChannelPtr const & channel, b
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -201,16 +201,12 @@ void PvaClientMonitor::checkMonitorState()
|
||||
|
||||
string PvaClientMonitor::getRequesterName()
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return string("PvaClientMonitor::getRequesterName() PvaClient isDestroyed");
|
||||
return yyy->getRequesterName();
|
||||
return pvaClientChannel->getRequesterName();
|
||||
}
|
||||
|
||||
void PvaClientMonitor::message(string const & message,MessageType messageType)
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return;
|
||||
yyy->message(message, messageType);
|
||||
pvaClientChannel->message(message,messageType);
|
||||
}
|
||||
|
||||
void PvaClientMonitor::monitorConnect(
|
||||
@@ -226,19 +222,24 @@ void PvaClientMonitor::monitorConnect(
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
this->monitor = monitor;
|
||||
if(!status.isOK()) {
|
||||
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;
|
||||
monitorConnectStatus = status;
|
||||
connectState = connected;
|
||||
if(isStarted) {
|
||||
if(PvaClient::getDebug()) {
|
||||
@@ -247,6 +248,9 @@ void PvaClientMonitor::monitorConnect(
|
||||
<< " is already started "
|
||||
<< endl;
|
||||
}
|
||||
waitForConnect.signal();
|
||||
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
|
||||
if(req) req->monitorConnect(status,shared_from_this(),structure);
|
||||
return;
|
||||
}
|
||||
pvaClientData = PvaClientMonitorData::create(structure);
|
||||
@@ -276,7 +280,7 @@ void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
|
||||
cout << "PvaClientMonitor::monitorEvent"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
|
||||
if(req) req->event(shared_from_this());
|
||||
if(userWait) waitForEvent.signal();
|
||||
@@ -288,9 +292,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
|
||||
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
|
||||
if(req) {
|
||||
req->unlisten();
|
||||
return;
|
||||
}
|
||||
cerr << pvaClientChannel->getChannel()->getChannelName() + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +302,7 @@ void PvaClientMonitor::connect()
|
||||
issueConnect();
|
||||
Status status = waitConnect();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::connect "
|
||||
+ status.getMessage();
|
||||
@@ -327,20 +329,7 @@ Status PvaClientMonitor::waitConnect()
|
||||
<< pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(connectState==connected) {
|
||||
if(!monitorConnectStatus.isOK()) connectState = connectIdle;
|
||||
return monitorConnectStatus;
|
||||
}
|
||||
if(connectState!=connectWait) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::waitConnect illegal connect state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
waitForConnect.wait();
|
||||
connectState = monitorConnectStatus.isOK() ? connected : connectIdle;
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientMonitor::waitConnect"
|
||||
<< " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
|
||||
@@ -434,21 +423,11 @@ bool PvaClientMonitor::poll()
|
||||
<< endl;
|
||||
}
|
||||
checkMonitorState();
|
||||
if(!isStarted) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::poll illegal state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(userPoll) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::poll did not release last";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
monitorElement = monitor->poll();
|
||||
if(!monitorElement) return false;
|
||||
userPoll = true;
|
||||
pvaClientData->setData(monitorElement);
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PvaClientMonitor::waitEvent(double secondsToWait)
|
||||
@@ -481,11 +460,6 @@ void PvaClientMonitor::releaseEvent()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(!isStarted) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::releaseEvent monitor not started ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(!userPoll) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientMonitor::releaseEvent did not call poll";
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -53,43 +52,16 @@ PvaClientMonitorDataPtr PvaClientMonitorData::create(StructureConstPtr const & s
|
||||
}
|
||||
|
||||
PvaClientMonitorData::PvaClientMonitorData(StructureConstPtr const & structure)
|
||||
: structure(structure)
|
||||
: PvaClientData(structure)
|
||||
{
|
||||
messagePrefix = "";
|
||||
}
|
||||
|
||||
void PvaClientMonitorData::setData(MonitorElementPtr const & monitorElement)
|
||||
{
|
||||
pvStructure = monitorElement->pvStructurePtr;
|
||||
changedBitSet = monitorElement->changedBitSet;
|
||||
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
|
||||
BitSetPtr changedBitSet = monitorElement->changedBitSet;
|
||||
PvaClientData::setData(pvStructure,changedBitSet);
|
||||
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()
|
||||
@@ -98,24 +70,6 @@ BitSetPtr PvaClientMonitorData::getOverrunBitSet()
|
||||
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)
|
||||
{
|
||||
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
|
||||
@@ -123,9 +77,9 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
|
||||
PVFieldPtr pvField;
|
||||
while(nextSet!=string::npos) {
|
||||
if(nextSet==0) {
|
||||
pvField = pvStructure;
|
||||
pvField = getPVStructure();
|
||||
} else {
|
||||
pvField = pvStructure->getSubField(nextSet);
|
||||
pvField = getPVStructure()->getSubField(nextSet);
|
||||
}
|
||||
string name = pvField->getFullName();
|
||||
out << name << " = " << pvField << endl;
|
||||
@@ -134,135 +88,4 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & 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);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -17,9 +17,6 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -31,26 +28,32 @@ static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create()
|
||||
|
||||
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const string> const & channelNames,
|
||||
shared_vector<const string> const & channelNames,
|
||||
string const & providerName,
|
||||
size_t maxNotConnected)
|
||||
size_t maxNotConnected,
|
||||
shared_vector<const string> const & providerNames)
|
||||
{
|
||||
return PvaClientMultiChannelPtr(
|
||||
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
|
||||
new PvaClientMultiChannel(
|
||||
pvaClient,channelNames,providerName,maxNotConnected,providerNames));
|
||||
}
|
||||
|
||||
|
||||
PvaClientMultiChannel::PvaClientMultiChannel(
|
||||
PvaClientPtr const &pvaClient,
|
||||
epics::pvData::shared_vector<const string> const & channelName,
|
||||
shared_vector<const string> const & channelNames,
|
||||
string const & providerName,
|
||||
size_t maxNotConnected)
|
||||
size_t maxNotConnected,
|
||||
shared_vector<const string> const & providerNames)
|
||||
: pvaClient(pvaClient),
|
||||
channelName(channelName),
|
||||
channelNames(channelNames),
|
||||
providerName(providerName),
|
||||
maxNotConnected(maxNotConnected),
|
||||
numChannel(channelName.size()),
|
||||
providerNames(providerNames),
|
||||
numChannel(channelNames.size()),
|
||||
numProviderNames(providerNames.size()),
|
||||
numConnected(0),
|
||||
firstConnect(true),
|
||||
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
|
||||
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
|
||||
createRequest(CreateRequest::create())
|
||||
@@ -65,25 +68,34 @@ PvaClientMultiChannel::~PvaClientMultiChannel()
|
||||
|
||||
void PvaClientMultiChannel::checkConnected()
|
||||
{
|
||||
if(numConnected==0) connect();
|
||||
if(firstConnect) {
|
||||
connect();
|
||||
firstConnect = false;
|
||||
}
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
|
||||
shared_vector<const string> PvaClientMultiChannel::getChannelNames()
|
||||
{
|
||||
return channelName;
|
||||
return channelNames;
|
||||
}
|
||||
|
||||
Status PvaClientMultiChannel::connect(double timeout)
|
||||
{
|
||||
if(!firstConnect) return Status::Ok;
|
||||
firstConnect = false;
|
||||
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();
|
||||
}
|
||||
Status returnStatus = Status::Ok;
|
||||
Status status = Status::Ok;
|
||||
size_t numBad = 0;
|
||||
for(size_t i=0; i< numChannel; ++i) {
|
||||
if(numBad==0) {
|
||||
if(numBad==0) {
|
||||
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
||||
} else {
|
||||
status = pvaClientChannelArray[i]->waitConnect(.001);
|
||||
@@ -91,11 +103,10 @@ Status PvaClientMultiChannel::connect(double timeout)
|
||||
if(status.isOK()) {
|
||||
++numConnected;
|
||||
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;
|
||||
}
|
||||
@@ -118,7 +129,7 @@ bool PvaClientMultiChannel::connectionChange()
|
||||
return false;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
||||
shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
|
||||
{
|
||||
for(size_t i=0; i<numChannel; ++i) {
|
||||
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
|
||||
@@ -143,7 +154,7 @@ PvaClientPtr PvaClientMultiChannel::getPvaClient()
|
||||
return pvaClient;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
|
||||
{
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
|
||||
@@ -40,7 +39,7 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
doubleValue(shared_vector<double>(nchannel)),
|
||||
doubleValue( shared_vector<double>(nchannel)),
|
||||
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
|
||||
isGetConnected(false)
|
||||
{
|
||||
@@ -54,7 +53,7 @@ PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
|
||||
|
||||
void PvaClientMultiGetDouble::connect()
|
||||
{
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
shared_vector<epics::pvData::boolean>isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
string request = "value";
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
@@ -76,14 +75,14 @@ void PvaClientMultiGetDouble::connect()
|
||||
isGetConnected = true;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
{
|
||||
if(!isGetConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(!pvaClientGet[i]) pvaClientGet[i]=pvaClientChannelArray[i]->createGet("value");
|
||||
pvaClientGet[i]->issueGet();
|
||||
}
|
||||
}
|
||||
@@ -97,13 +96,22 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i])
|
||||
{
|
||||
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
|
||||
doubleValue[i] = getConvert()->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 {
|
||||
doubleValue[i] = epicsNAN;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
|
||||
@@ -91,6 +90,17 @@ bool PvaClientMultiMonitorDouble::poll()
|
||||
for(size_t i=0; i<nchannel; ++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()) {
|
||||
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
|
||||
pvaClientMonitor[i]->releaseEvent();
|
||||
@@ -117,7 +127,7 @@ bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
|
||||
return false;
|
||||
}
|
||||
|
||||
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
|
||||
shared_vector<double> PvaClientMultiMonitorDouble::get()
|
||||
{
|
||||
return doubleValue;
|
||||
}
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
|
||||
@@ -77,7 +76,7 @@ void PvaClientMultiPutDouble::connect()
|
||||
isPutConnected = true;
|
||||
}
|
||||
|
||||
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
|
||||
void PvaClientMultiPutDouble::put(shared_vector<double> const &data)
|
||||
{
|
||||
if(!isPutConnected) connect();
|
||||
if(data.size()!=nchannel) {
|
||||
@@ -87,10 +86,18 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(!pvaClientPut[i]) pvaClientPut[i]=pvaClientChannelArray[i]->createPut("value");
|
||||
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
|
||||
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
|
||||
getConvert()->fromDouble(pvValue,data[i]);
|
||||
pvaClientPut[i]->issuePut();
|
||||
PVScalarPtr pvScalar= pvTop->getSubField<PVScalar>("value");
|
||||
if(pvScalar && ScalarTypeFunc::isNumeric(pvScalar->getScalar()->getScalarType())) {
|
||||
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]) {
|
||||
Status status = pvaClientPut[i]->waitPut();
|
||||
|
||||
@@ -15,16 +15,15 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
PVStructurePtr const & pvRequest)
|
||||
@@ -34,22 +33,21 @@ PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
|
||||
}
|
||||
|
||||
PvaClientNTMultiData::PvaClientNTMultiData(
|
||||
epics::pvData::UnionConstPtr const & u,
|
||||
UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
gotAlarm(false),
|
||||
gotTimeStamp(false)
|
||||
|
||||
{
|
||||
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
|
||||
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
|
||||
if(!pvValue) {
|
||||
throw std::runtime_error("pvRequest did not specify value");
|
||||
}
|
||||
changeFlags = shared_vector<epics::pvData::boolean>(nchannel);
|
||||
topPVStructure.resize(nchannel);
|
||||
|
||||
unionValue.resize(nchannel);
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
for(size_t i=0; i< nchannel; ++i) {
|
||||
@@ -68,7 +66,7 @@ PvaClientNTMultiData::PvaClientNTMultiData(
|
||||
severity.resize(nchannel);
|
||||
status.resize(nchannel);
|
||||
message.resize(nchannel);
|
||||
|
||||
|
||||
}
|
||||
if(pvRequest->getSubField("field.timeStamp")) {
|
||||
gotTimeStamp = true;
|
||||
@@ -89,30 +87,24 @@ PvaClientNTMultiData::~PvaClientNTMultiData()
|
||||
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
|
||||
}
|
||||
|
||||
|
||||
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(
|
||||
PVStructurePtr const &pvStructure,size_t index)
|
||||
{
|
||||
topPVStructure[index] = pvStructure;
|
||||
}
|
||||
|
||||
shared_vector<epics::pvData::boolean> PvaClientNTMultiData::getChannelChangeFlags()
|
||||
{
|
||||
return changeFlags;
|
||||
}
|
||||
|
||||
size_t PvaClientNTMultiData::getNumber()
|
||||
{
|
||||
return nchannel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PvaClientNTMultiData::startDeltaTime()
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
@@ -138,28 +130,49 @@ void PvaClientNTMultiData::startDeltaTime()
|
||||
}
|
||||
|
||||
|
||||
void PvaClientNTMultiData::endDeltaTime()
|
||||
void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
|
||||
{
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
PVStructurePtr pvst = topPVStructure[i];
|
||||
if(!pvst) {
|
||||
unionValue[i] = PVUnionPtr();
|
||||
} else if(unionValue[i]) {
|
||||
unionValue[i]->set(pvst->getSubField("value"));
|
||||
changeFlags[i] = false;
|
||||
if(pvst&&unionValue[i]) {
|
||||
changeFlags[i] = true;
|
||||
if(valueOnly) {
|
||||
PVFieldPtr pvValue = pvst->getSubField("value");
|
||||
if(pvValue) {
|
||||
unionValue[i]->set(pvst->getSubField("value"));
|
||||
}
|
||||
} else {
|
||||
unionValue[i]->set(pvst);
|
||||
}
|
||||
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();
|
||||
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)
|
||||
{
|
||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,7 +187,7 @@ NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
|
||||
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure);
|
||||
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
|
||||
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];
|
||||
ntMultiChannel->getValue()->replace(freeze(val));
|
||||
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
+12
-12
@@ -15,13 +15,12 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
|
||||
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
|
||||
@@ -39,7 +38,7 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
|
||||
UnionConstPtr const & u,
|
||||
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
PVStructurePtr const & pvRequest)
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
pvRequest(pvRequest),
|
||||
@@ -64,13 +63,10 @@ void PvaClientNTMultiGet::connect()
|
||||
{
|
||||
pvaClientGet.resize(nchannel);
|
||||
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)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
|
||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
|
||||
pvaClientGet[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
@@ -79,7 +75,7 @@ void PvaClientNTMultiGet::connect()
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelGet::waitConnect " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -87,14 +83,18 @@ void PvaClientNTMultiGet::connect()
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
void PvaClientNTMultiGet::get()
|
||||
void PvaClientNTMultiGet::get(bool valueOnly)
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
|
||||
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
if(!pvaClientGet[i]){
|
||||
pvaClientGet[i]=pvaClientChannelArray[i]->createGet(pvRequest);
|
||||
pvaClientGet[i]->connect();
|
||||
}
|
||||
pvaClientGet[i]->issueGet();
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ void PvaClientNTMultiGet::get()
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientGet[i]->waitGet();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelGet::waitGet " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ void PvaClientNTMultiGet::get()
|
||||
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
||||
}
|
||||
}
|
||||
pvaClientNTMultiData->endDeltaTime();
|
||||
pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||
}
|
||||
|
||||
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
||||
|
||||
@@ -18,18 +18,17 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
PvaClientChannelArray const &pvaClientChannelArray,
|
||||
epics::pvData::PVStructurePtr const & pvRequest)
|
||||
PVStructurePtr const & pvRequest)
|
||||
{
|
||||
UnionConstPtr u = getFieldCreate()->createVariantUnion();
|
||||
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
|
||||
@@ -68,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
|
||||
{
|
||||
pvaClientMonitor.resize(nchannel);
|
||||
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)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
|
||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
|
||||
pvaClientMonitor[i]->issueConnect();
|
||||
}
|
||||
}
|
||||
@@ -83,7 +79,7 @@ void PvaClientNTMultiMonitor::connect()
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientMonitor[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -95,24 +91,29 @@ void PvaClientNTMultiMonitor::connect()
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
bool PvaClientNTMultiMonitor::poll()
|
||||
bool PvaClientNTMultiMonitor::poll(bool valueOnly)
|
||||
{
|
||||
if(!isConnected) connect();
|
||||
bool result = false;
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||
pvaClientNTMultiData->startDeltaTime();
|
||||
for(size_t i=0; i<nchannel; ++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(
|
||||
pvaClientMonitor[i]->getData()->getPVStructure(),i);
|
||||
pvaClientMonitor[i]->getData()->getPVStructure(),i);
|
||||
pvaClientMonitor[i]->releaseEvent();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result) pvaClientNTMultiData->endDeltaTime();
|
||||
}
|
||||
if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
+43
-13
@@ -17,13 +17,12 @@
|
||||
|
||||
#include <pv/pvaClientMultiChannel.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::nt;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
namespace epics { namespace pvaClient {
|
||||
|
||||
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
|
||||
PvaClientMultiChannelPtr const &pvaMultiChannel,
|
||||
@@ -39,8 +38,8 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
|
||||
: pvaClientMultiChannel(pvaClientMultiChannel),
|
||||
pvaClientChannelArray(pvaClientChannelArray),
|
||||
nchannel(pvaClientChannelArray.size()),
|
||||
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
|
||||
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
|
||||
unionValue(shared_vector<PVUnionPtr>(nchannel,PVUnionPtr())),
|
||||
value(shared_vector<PVFieldPtr>(nchannel,PVFieldPtr())),
|
||||
isConnected(false)
|
||||
{
|
||||
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
|
||||
@@ -68,7 +67,7 @@ void PvaClientNTMultiPut::connect()
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitConnect();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelPut::waitConnect " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -84,7 +83,7 @@ void PvaClientNTMultiPut::connect()
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitGet();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelPut::waitGet " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -103,9 +102,26 @@ void PvaClientNTMultiPut::connect()
|
||||
this->isConnected = true;
|
||||
}
|
||||
|
||||
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
|
||||
shared_vector<PVUnionPtr> PvaClientNTMultiPut::getValues()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -116,15 +132,29 @@ void PvaClientNTMultiPut::put()
|
||||
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());
|
||||
}
|
||||
value[i]->copy(*unionValue[i]->get());
|
||||
pvaClientPut[i]->issuePut();
|
||||
}
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitPut();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelPut::waitPut " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
for(size_t i=0; i<nchannel; ++i)
|
||||
{
|
||||
if(isConnected[i]) {
|
||||
Status status = pvaClientPut[i]->waitPut();
|
||||
if(status.isOK()) continue;
|
||||
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
|
||||
+ " PvaChannelPut::waitPut " + status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-91
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -43,7 +42,7 @@ public:
|
||||
return clientProcess->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||
if(!clientProcess) return;
|
||||
clientProcess->message(message,messageType);
|
||||
@@ -55,7 +54,7 @@ public:
|
||||
{
|
||||
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
|
||||
if(!clientProcess) return;
|
||||
clientProcess->channelProcessConnect(status,channelProcess);
|
||||
clientProcess->channelProcessConnect(status,channelProcess);
|
||||
}
|
||||
|
||||
virtual void processDone(
|
||||
@@ -112,63 +111,14 @@ PvaClientProcess::~PvaClientProcess()
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientProcess::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientProcess::channelStateChange"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " isConnected " << (isConnected ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
if(isConnected)
|
||||
{
|
||||
connectState = connectActive;
|
||||
channelProcess = pvaClientChannel->getChannel()->createChannelProcess(channelProcessRequester,pvRequest);
|
||||
}
|
||||
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
|
||||
if(req) {
|
||||
req->channelStateChange(pvaClientChannel,isConnected);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientProcess::checkProcessState()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientProcess::checkProcessState"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(!pvaClientChannel->getChannel()->isConnected()) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientProcess::checkProcessState channel not connected ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(connectState==connectIdle) {
|
||||
connect();
|
||||
}
|
||||
if(connectState==connectActive){
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " "
|
||||
+ channelProcessConnectStatus.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
if(processState==processIdle) process();
|
||||
}
|
||||
|
||||
|
||||
// from ChannelProcessRequester
|
||||
string PvaClientProcess::getRequesterName()
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
||||
return yyy->getRequesterName();
|
||||
return pvaClientChannel->getRequesterName();
|
||||
}
|
||||
|
||||
void PvaClientProcess::message(string const & message,MessageType messageType)
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
|
||||
yyy->message(message, messageType);
|
||||
pvaClientChannel->message(message,messageType);
|
||||
}
|
||||
|
||||
void PvaClientProcess::channelProcessConnect(
|
||||
@@ -183,25 +133,17 @@ void PvaClientProcess::channelProcessConnect(
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
this->channelProcess = channelProcess;
|
||||
channelProcessConnectStatus = status;
|
||||
if(status.isOK()) {
|
||||
channelProcessConnectStatus = status;
|
||||
this->channelProcess = channelProcess;
|
||||
connectState = connected;
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << pvRequest;
|
||||
string message = string("PvaClientProcess::channelProcessConnect")
|
||||
+ "\npvRequest\n" + ss.str()
|
||||
+ "\nerror\n" + status.getMessage();
|
||||
channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
}
|
||||
waitForConnect.signal();
|
||||
}
|
||||
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
|
||||
if(req) {
|
||||
req->channelProcessConnect(status,shared_from_this());
|
||||
}
|
||||
waitForConnect.signal();
|
||||
|
||||
}
|
||||
|
||||
void PvaClientProcess::processDone(
|
||||
@@ -218,13 +160,12 @@ void PvaClientProcess::processDone(
|
||||
Lock xx(mutex);
|
||||
channelProcessStatus = status;
|
||||
processState = processComplete;
|
||||
waitForProcess.signal();
|
||||
}
|
||||
|
||||
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
|
||||
if(req) {
|
||||
req->processDone(status,shared_from_this());
|
||||
}
|
||||
waitForProcess.signal();
|
||||
}
|
||||
|
||||
void PvaClientProcess::connect()
|
||||
@@ -255,6 +196,7 @@ void PvaClientProcess::issueConnect()
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
connectState = connectActive;
|
||||
channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||
channelProcess = pvaClientChannel->getChannel()->createChannelProcess(channelProcessRequester,pvRequest);
|
||||
}
|
||||
|
||||
@@ -265,17 +207,7 @@ Status PvaClientProcess::waitConnect()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(connectState==connected) {
|
||||
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelProcessConnectStatus;
|
||||
}
|
||||
if(connectState!=connectActive) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " pvaClientProcess illegal connect state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForConnect.wait();
|
||||
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelProcessConnectStatus;
|
||||
}
|
||||
|
||||
@@ -302,7 +234,7 @@ void PvaClientProcess::issueProcess()
|
||||
<< endl;
|
||||
}
|
||||
if(connectState==connectIdle) connect();
|
||||
if(processState!=processIdle) {
|
||||
if(processState==processActive) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientProcess::issueProcess process aleady active ";
|
||||
throw std::runtime_error(message);
|
||||
@@ -318,18 +250,6 @@ Status PvaClientProcess::waitProcess()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(processState==processComplete) {
|
||||
processState = processIdle;
|
||||
return channelProcessStatus;
|
||||
}
|
||||
if(processState!=processActive){
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientProcess::waitProcess llegal process state";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
waitForProcess.wait();
|
||||
processState = processComplete;
|
||||
return channelProcessStatus;
|
||||
|
||||
+36
-86
@@ -15,7 +15,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -43,7 +42,7 @@ public:
|
||||
return clientPut->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||
if(!clientPut) return;
|
||||
clientPut->message(message,messageType);
|
||||
@@ -56,7 +55,7 @@ public:
|
||||
{
|
||||
PvaClientPutPtr clientPut(pvaClientPut.lock());
|
||||
if(!clientPut) return;
|
||||
clientPut->channelPutConnect(status,channelPut,structure);
|
||||
clientPut->channelPutConnect(status,channelPut,structure);
|
||||
}
|
||||
|
||||
virtual void getDone(
|
||||
@@ -118,29 +117,11 @@ PvaClientPut::~PvaClientPut()
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientPut::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientPut::channelStateChange"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " isConnected " << (isConnected ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
if(isConnected&&!channelPut)
|
||||
{
|
||||
connectState = connectActive;
|
||||
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
|
||||
}
|
||||
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
|
||||
if(req) {
|
||||
req->channelStateChange(pvaClientChannel,isConnected);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientPut::checkPutState()
|
||||
void PvaClientPut::checkConnectState()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientPut::checkPutState"
|
||||
cout << "PvaClientPut::checkConnectState"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
@@ -157,16 +138,12 @@ void PvaClientPut::checkPutState()
|
||||
|
||||
string PvaClientPut::getRequesterName()
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed");
|
||||
return yyy->getRequesterName();
|
||||
return pvaClientChannel->getRequesterName();
|
||||
}
|
||||
|
||||
void PvaClientPut::message(string const & message,MessageType messageType)
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return;
|
||||
yyy->message(message, messageType);
|
||||
pvaClientChannel->message(message,messageType);
|
||||
}
|
||||
|
||||
void PvaClientPut::channelPutConnect(
|
||||
@@ -182,27 +159,19 @@ void PvaClientPut::channelPutConnect(
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
this->channelPut = channelPut;
|
||||
channelPutConnectStatus = status;
|
||||
if(status.isOK()) {
|
||||
channelPutConnectStatus = status;
|
||||
this->channelPut = channelPut;
|
||||
connectState = connected;
|
||||
pvaClientData = PvaClientPutData::create(structure);
|
||||
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << pvRequest;
|
||||
string message = string("\nPvaClientPut::channelPutConnect)")
|
||||
+ "\npvRequest\n" + ss.str()
|
||||
+ "\nerror\n" + status.getMessage();
|
||||
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
}
|
||||
waitForConnect.signal();
|
||||
}
|
||||
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||
if(req) {
|
||||
req->channelPutConnect(status,shared_from_this());
|
||||
}
|
||||
waitForConnect.signal();
|
||||
|
||||
}
|
||||
|
||||
void PvaClientPut::getDone(
|
||||
@@ -217,19 +186,23 @@ void PvaClientPut::getDone(
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
channelGetPutStatus = status;
|
||||
if(status.isOK()) {
|
||||
PVStructurePtr pvs = pvaClientData->getPVStructure();
|
||||
pvs->copyUnchecked(*pvStructure,*bitSet);
|
||||
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(
|
||||
@@ -242,12 +215,14 @@ void PvaClientPut::putDone(
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
channelGetPutStatus = status;
|
||||
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||
if(req) {
|
||||
req->putDone(status,shared_from_this());
|
||||
{
|
||||
Lock xx(mutex);
|
||||
channelGetPutStatus = status;
|
||||
putState = putComplete;
|
||||
waitForGetPut.signal();
|
||||
}
|
||||
waitForGetPut.signal();
|
||||
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
|
||||
if(req) { req->putDone(status,shared_from_this());}
|
||||
}
|
||||
|
||||
void PvaClientPut::connect()
|
||||
@@ -260,7 +235,7 @@ void PvaClientPut::connect()
|
||||
issueConnect();
|
||||
Status status = waitConnect();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::connect "
|
||||
+ status.getMessage();
|
||||
@@ -282,7 +257,7 @@ void PvaClientPut::issueConnect()
|
||||
connectState = connectActive;
|
||||
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
|
||||
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
|
||||
|
||||
|
||||
}
|
||||
|
||||
Status PvaClientPut::waitConnect()
|
||||
@@ -292,20 +267,7 @@ Status PvaClientPut::waitConnect()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(connectState==connected) {
|
||||
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelPutConnectStatus;
|
||||
}
|
||||
if(connectState!=connectActive) {
|
||||
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::waitConnect illegal connect state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
waitForConnect.wait();
|
||||
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelPutConnectStatus;
|
||||
}
|
||||
|
||||
@@ -319,7 +281,7 @@ void PvaClientPut::get()
|
||||
issueGet();
|
||||
Status status = waitGet();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::get "
|
||||
+ status.getMessage();
|
||||
@@ -351,12 +313,6 @@ Status PvaClientPut::waitGet()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(putState!=getActive){
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::waitGet illegal put state";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForGetPut.wait();
|
||||
putState = putComplete;
|
||||
return channelGetPutStatus;
|
||||
@@ -384,15 +340,15 @@ void PvaClientPut::issuePut()
|
||||
if(PvaClient::getDebug()) {
|
||||
cout << "PvaClientPut::issuePut"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " pvStructure\n" << pvaClientData->getPVStructure()
|
||||
<< " pvStructure\n" << pvaClientData->getPVStructure()
|
||||
<< " bitSet " << *pvaClientData->getChangedBitSet() << endl
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
if(connectState==connectIdle) connect();
|
||||
if(putState==getActive || putState==putActive) {
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ "PvaClientPut::issueGet get or put aleady active ";
|
||||
+ " PvaClientPut::issuePut get or put aleady active ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
putState = putActive;
|
||||
@@ -406,12 +362,6 @@ Status PvaClientPut::waitPut()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(putState!=putActive){
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::waitPut illegal put state";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForGetPut.wait();
|
||||
putState = putComplete;
|
||||
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
|
||||
@@ -425,7 +375,7 @@ PvaClientPutDataPtr PvaClientPut::getData()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
checkPutState();
|
||||
checkConnectState();
|
||||
if(putState==putIdle) get();
|
||||
return pvaClientData;
|
||||
}
|
||||
|
||||
+59
-168
@@ -25,6 +25,10 @@ using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvaClient {
|
||||
static ConvertPtr convert = getConvert();
|
||||
static string notCompatibleScalar("value is not a compatible scalar");
|
||||
static string notDoubleArray("value is not a doubleArray");
|
||||
static string notStringArray("value is not a stringArray");
|
||||
|
||||
class PvaClientPostHandlerPvt: public PostHandler
|
||||
{
|
||||
@@ -36,28 +40,21 @@ public:
|
||||
void postPut() { putData->postPut(fieldNumber);}
|
||||
};
|
||||
|
||||
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
||||
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 notArray("value is not an array");
|
||||
static string notScalarArray("value is not a scalarArray");
|
||||
static string notDoubleArray("value is not a doubleArray");
|
||||
static string notStringArray("value is not a stringArray");
|
||||
|
||||
PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure)
|
||||
{
|
||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::create\n";
|
||||
PvaClientPutDataPtr epv(new PvaClientPutData(structure));
|
||||
return epv;
|
||||
}
|
||||
|
||||
PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
||||
: structure(structure),
|
||||
pvStructure(getPVDataCreate()->createPVStructure(structure)),
|
||||
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
|
||||
: PvaClientData(structure)
|
||||
{
|
||||
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();
|
||||
postHandler.resize(nfields);
|
||||
PVFieldPtr pvField;
|
||||
@@ -71,145 +68,18 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
||||
}
|
||||
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)
|
||||
{
|
||||
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();
|
||||
if(scalarType==pvDouble) {
|
||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
||||
@@ -217,47 +87,68 @@ void PvaClientPutData::putDouble(double value)
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
||||
{
|
||||
checkValue();
|
||||
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
|
||||
if(!pv) {
|
||||
throw std::runtime_error(messagePrefix + notDoubleArray);
|
||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
|
||||
PVFieldPtr pvField = getSinglePVField();
|
||||
Type type = pvField->getField()->getType();
|
||||
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)
|
||||
{
|
||||
checkValue();
|
||||
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
|
||||
if(!pv) {
|
||||
throw std::runtime_error(messagePrefix + notStringArray);
|
||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
|
||||
PVFieldPtr pvField = getSinglePVField();
|
||||
Type type = pvField->getField()->getType();
|
||||
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();
|
||||
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
|
||||
if(!pv) {
|
||||
throw std::runtime_error(messagePrefix + notScalarArray);
|
||||
}
|
||||
convert->fromStringArray(pv,0,value.size(),value,0);
|
||||
size_t length = value.size();
|
||||
shared_vector<string> val(length);
|
||||
for(size_t i=0; i < length; ++i) val[i] = value[i];
|
||||
putStringArray(freeze(val));
|
||||
return;
|
||||
}
|
||||
|
||||
void PvaClientPutData::postPut(size_t fieldNumber)
|
||||
{
|
||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::postPut\n";
|
||||
getChangedBitSet()->set(fieldNumber);
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
+48
-108
@@ -14,7 +14,6 @@
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -42,7 +41,7 @@ public:
|
||||
return clientPutGet->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||
if(!clientPutGet) return;
|
||||
clientPutGet->message(message,messageType);
|
||||
@@ -56,7 +55,7 @@ public:
|
||||
{
|
||||
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
|
||||
if(!clientPutGet) return;
|
||||
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
|
||||
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
|
||||
}
|
||||
|
||||
virtual void putGetDone(
|
||||
@@ -131,25 +130,6 @@ PvaClientPutGet::~PvaClientPutGet()
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientPutGet::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientPutGet::channelStateChange"
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< " isConnected " << (isConnected ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
if(isConnected&&!channelPutGet)
|
||||
{
|
||||
connectState = connectActive;
|
||||
channelPutGet = pvaClientChannel->getChannel()->createChannelPutGet(channelPutGetRequester,pvRequest);
|
||||
}
|
||||
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
|
||||
if(req) {
|
||||
req->channelStateChange(pvaClientChannel,isConnected);
|
||||
}
|
||||
}
|
||||
|
||||
void PvaClientPutGet::checkPutGetState()
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
@@ -170,16 +150,12 @@ void PvaClientPutGet::checkPutGetState()
|
||||
|
||||
string PvaClientPutGet::getRequesterName()
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed");
|
||||
return yyy->getRequesterName();
|
||||
return pvaClientChannel->getRequesterName();
|
||||
}
|
||||
|
||||
void PvaClientPutGet::message(string const & message,MessageType messageType)
|
||||
{
|
||||
PvaClientPtr yyy = pvaClient.lock();
|
||||
if(!yyy) return;
|
||||
yyy->message(message, messageType);
|
||||
pvaClientChannel->message(message,messageType);
|
||||
}
|
||||
|
||||
void PvaClientPutGet::channelPutGetConnect(
|
||||
@@ -196,30 +172,21 @@ void PvaClientPutGet::channelPutGetConnect(
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
this->channelPutGet = channelPutGet;
|
||||
channelPutGetConnectStatus = status;
|
||||
if(status.isOK()) {
|
||||
channelPutGetConnectStatus = status;
|
||||
this->channelPutGet = channelPutGet;
|
||||
connectState = connected;
|
||||
pvaClientPutData = PvaClientPutData::create(putStructure);
|
||||
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
|
||||
pvaClientGetData = PvaClientGetData::create(getStructure);
|
||||
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
|
||||
|
||||
} else {
|
||||
stringstream ss;
|
||||
ss << pvRequest;
|
||||
string message = string("\nPvaClientPutGet::channelPutGetConnect)")
|
||||
+ "\npvRequest\n" + ss.str()
|
||||
+ "\nerror\n" + status.getMessage();
|
||||
channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
}
|
||||
waitForConnect.signal();
|
||||
}
|
||||
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||
if(req) {
|
||||
req->channelPutGetConnect(status,shared_from_this());
|
||||
}
|
||||
waitForConnect.signal();
|
||||
|
||||
}
|
||||
|
||||
void PvaClientPutGet::putGetDone(
|
||||
@@ -234,19 +201,19 @@ void PvaClientPutGet::putGetDone(
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
channelPutGetStatus = status;
|
||||
if(status.isOK()) {
|
||||
PVStructurePtr pvs = pvaClientGetData->getPVStructure();
|
||||
pvs->copyUnchecked(*getPVStructure,*getChangedBitSet);
|
||||
BitSetPtr bs = pvaClientGetData->getChangedBitSet();
|
||||
bs->clear();
|
||||
*bs |= *getChangedBitSet;
|
||||
{
|
||||
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(
|
||||
@@ -261,19 +228,23 @@ void PvaClientPutGet::getPutDone(
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
channelPutGetStatus = status;
|
||||
if(status.isOK()) {
|
||||
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
|
||||
pvs->copyUnchecked(*putPVStructure,*putBitSet);
|
||||
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(
|
||||
@@ -288,19 +259,19 @@ void PvaClientPutGet::getGetDone(
|
||||
<< " status.isOK " << (status.isOK() ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
channelPutGetStatus = status;
|
||||
if(status.isOK()) {
|
||||
PVStructurePtr pvs = pvaClientGetData->getPVStructure();
|
||||
pvs->copyUnchecked(*getPVStructure,*getChangedBitSet);
|
||||
BitSetPtr bs = pvaClientGetData->getChangedBitSet();
|
||||
bs->clear();
|
||||
*bs |= *getChangedBitSet;
|
||||
{
|
||||
Lock xx(mutex);
|
||||
channelPutGetStatus = status;
|
||||
if(status.isOK()) {
|
||||
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
|
||||
}
|
||||
putGetState = putGetComplete;
|
||||
waitForPutGet.signal();
|
||||
}
|
||||
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
|
||||
if(req) {
|
||||
req->getGetDone(status,shared_from_this());
|
||||
}
|
||||
waitForPutGet.signal();
|
||||
}
|
||||
|
||||
void PvaClientPutGet::connect()
|
||||
@@ -313,7 +284,7 @@ void PvaClientPutGet::connect()
|
||||
issueConnect();
|
||||
Status status = waitConnect();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPutGet::connect "
|
||||
+ status.getMessage();
|
||||
@@ -345,21 +316,7 @@ Status PvaClientPutGet::waitConnect()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
if(connectState==connected) {
|
||||
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelPutGetConnectStatus;
|
||||
}
|
||||
if(connectState!=connectActive) {
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPutGet::waitConnect illegal connect state ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
}
|
||||
waitForConnect.wait();
|
||||
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
|
||||
return channelPutGetConnectStatus;
|
||||
}
|
||||
|
||||
@@ -374,7 +331,7 @@ void PvaClientPutGet::putGet()
|
||||
issuePutGet();
|
||||
Status status = waitPutGet();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::putGet "
|
||||
+ status.getMessage();
|
||||
@@ -407,14 +364,7 @@ Status PvaClientPutGet::waitPutGet()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(putGetState!=putGetActive){
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPutGet::waitPutGet get or put aleady active ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForPutGet.wait();
|
||||
putGetState = putGetComplete;
|
||||
if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
|
||||
return channelPutGetStatus;
|
||||
}
|
||||
@@ -429,7 +379,7 @@ void PvaClientPutGet::getGet()
|
||||
issueGetGet();
|
||||
Status status = waitGetGet();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::getGet "
|
||||
+ status.getMessage();
|
||||
@@ -461,14 +411,7 @@ Status PvaClientPutGet::waitGetGet()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(putGetState!=putGetActive){
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPutGet::waitGetGet get or put aleady active ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForPutGet.wait();
|
||||
putGetState = putGetComplete;
|
||||
return channelPutGetStatus;
|
||||
}
|
||||
|
||||
@@ -482,7 +425,7 @@ void PvaClientPutGet::getPut()
|
||||
issueGetPut();
|
||||
Status status = waitGetPut();
|
||||
if(status.isOK()) return;
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPut::getPut "
|
||||
+ status.getMessage();
|
||||
@@ -514,14 +457,7 @@ Status PvaClientPutGet::waitGetPut()
|
||||
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
if(putGetState!=putGetActive){
|
||||
string message = string("channel ")
|
||||
+ pvaClientChannel->getChannel()->getChannelName()
|
||||
+ " PvaClientPutGet::waitGetPut get or put aleady active ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
waitForPutGet.wait();
|
||||
putGetState = putGetComplete;
|
||||
return channelPutGetStatus;
|
||||
}
|
||||
|
||||
@@ -533,7 +469,10 @@ PvaClientGetDataPtr PvaClientPutGet::getGetData()
|
||||
<< endl;
|
||||
}
|
||||
checkPutGetState();
|
||||
if(putGetState==putGetIdle) getGet();
|
||||
if(putGetState==putGetIdle){
|
||||
getGet();
|
||||
getPut();
|
||||
}
|
||||
return pvaClientGetData;
|
||||
}
|
||||
|
||||
@@ -545,7 +484,10 @@ PvaClientPutDataPtr PvaClientPutGet::getPutData()
|
||||
<< endl;
|
||||
}
|
||||
checkPutGetState();
|
||||
if(putGetState==putGetIdle) getPut();
|
||||
if(putGetState==putGetIdle){
|
||||
getGet();
|
||||
getPut();
|
||||
}
|
||||
return pvaClientPutData;
|
||||
}
|
||||
|
||||
@@ -565,6 +507,4 @@ PvaClientChannelPtr PvaClientPutGet::getPvaClientChannel()
|
||||
return pvaClientChannel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}}
|
||||
|
||||
+22
-14
@@ -12,13 +12,12 @@
|
||||
#include <sstream>
|
||||
#include <pv/event.h>
|
||||
#include <pv/bitSetUtil.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/pvaClient.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
@@ -46,14 +45,14 @@ public:
|
||||
return clientRPC->getRequesterName();
|
||||
}
|
||||
|
||||
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
|
||||
virtual void message(std::string const & message, MessageType messageType) {
|
||||
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||
if(!clientRPC) return;
|
||||
clientRPC->message(message,messageType);
|
||||
}
|
||||
|
||||
virtual void channelRPCConnect(
|
||||
const epics::pvData::Status& status,
|
||||
const Status& status,
|
||||
ChannelRPC::shared_pointer const & channelRPC)
|
||||
{
|
||||
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
|
||||
@@ -95,7 +94,7 @@ PvaClientRPC::PvaClientRPC(
|
||||
PvaClientPtr const &pvaClient,
|
||||
Channel::shared_pointer const & channel,
|
||||
PVStructurePtr const &pvRequest)
|
||||
:
|
||||
:
|
||||
connectState(connectIdle),
|
||||
pvaClient(pvaClient),
|
||||
channel(channel),
|
||||
@@ -105,7 +104,7 @@ PvaClientRPC::PvaClientRPC(
|
||||
{
|
||||
if(PvaClient::getDebug()) {
|
||||
cout<< "PvaClientRPC::PvaClientRPC()"
|
||||
<< " channelName " << channel->getChannelName()
|
||||
<< " channelName " << channel->getChannelName()
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
@@ -171,7 +170,7 @@ void PvaClientRPC::rpcConnect(
|
||||
cout << "PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
|
||||
}
|
||||
waitForConnect.signal();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void PvaClientRPC::requestDone(
|
||||
@@ -182,6 +181,7 @@ void PvaClientRPC::requestDone(
|
||||
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
|
||||
{
|
||||
Lock xx(mutex);
|
||||
requestStatus = status;
|
||||
if(PvaClient::getDebug()) {
|
||||
string channelName("disconnected");
|
||||
Channel::shared_pointer chan(channel.lock());
|
||||
@@ -195,7 +195,7 @@ void PvaClientRPC::requestDone(
|
||||
Channel::shared_pointer chan(channel.lock());
|
||||
if(chan) channelName = chan->getChannelName();
|
||||
string message = "channel "
|
||||
+ channelName
|
||||
+ channelName
|
||||
+" PvaClientRPC::requestDone"
|
||||
+ " but not active";
|
||||
throw std::runtime_error(message);
|
||||
@@ -222,11 +222,11 @@ void PvaClientRPC::connect()
|
||||
Channel::shared_pointer chan(channel.lock());
|
||||
string channelName("disconnected");
|
||||
if(chan) channelName = chan->getChannelName();
|
||||
string message = string("channel ")
|
||||
string message = string("channel ")
|
||||
+ channelName
|
||||
+ " PvaClientRPC::connect "
|
||||
+ status.getMessage();
|
||||
throw std::runtime_error(message);
|
||||
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
|
||||
void PvaClientRPC::issueConnect()
|
||||
@@ -237,7 +237,7 @@ void PvaClientRPC::issueConnect()
|
||||
string channelName("disconnected");
|
||||
if(chan) channelName = chan->getChannelName();
|
||||
string message = string("channel ")
|
||||
+ channelName
|
||||
+ channelName
|
||||
+ " pvaClientRPC already connected ";
|
||||
throw std::runtime_error(message);
|
||||
}
|
||||
@@ -307,10 +307,18 @@ PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer co
|
||||
string message = "channel "
|
||||
+ channelName
|
||||
+ " PvaClientRPC::request request timeout ";
|
||||
throw std::runtime_error(message);
|
||||
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||
}
|
||||
rpcState = rpcIdle;
|
||||
return pvResponse;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@@ -318,7 +326,7 @@ void PvaClientRPC::request(
|
||||
PVStructure::shared_pointer const & pvArgument,
|
||||
PvaClientRPCRequesterPtr const & pvaClientRPCRequester)
|
||||
{
|
||||
checkRPCState();
|
||||
checkRPCState();
|
||||
this->pvaClientRPCRequester = pvaClientRPCRequester;
|
||||
if(responseTimeout<=0.0) {
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user