Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 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 |
@@ -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
|
||||||
@@ -28,4 +28,3 @@ env:
|
|||||||
- BRBASE=7.0 RTEMS=4.9 TEST=NO
|
- BRBASE=7.0 RTEMS=4.9 TEST=NO
|
||||||
- BRBASE=3.16
|
- BRBASE=3.16
|
||||||
- BRBASE=3.15
|
- BRBASE=3.15
|
||||||
- BRBASE=3.14
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ PROJECT_NAME = pvaClientCPP
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER = 4.7.1
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
|
|||||||
# will be relative from the directory where doxygen is started.
|
# will be relative from the directory where doxygen is started.
|
||||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||||
|
|
||||||
STRIP_FROM_PATH =
|
STRIP_FROM_PATH = src
|
||||||
|
|
||||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
||||||
# path mentioned in the documentation of a class, which tells the reader which
|
# path mentioned in the documentation of a class, which tells the reader which
|
||||||
@@ -161,7 +161,7 @@ STRIP_FROM_PATH =
|
|||||||
# specify the list of include paths that are normally passed to the compiler
|
# specify the list of include paths that are normally passed to the compiler
|
||||||
# using the -I flag.
|
# using the -I flag.
|
||||||
|
|
||||||
STRIP_FROM_INC_PATH =
|
STRIP_FROM_INC_PATH = src
|
||||||
|
|
||||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
|
||||||
# less readable) file names. This can be useful is your file systems doesn't
|
# less readable) file names. This can be useful is your file systems doesn't
|
||||||
@@ -765,7 +765,8 @@ WARN_LOGFILE =
|
|||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = include
|
INPUT = src \
|
||||||
|
src/pv
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@@ -796,7 +797,7 @@ FILE_PATTERNS =
|
|||||||
# be searched for input files as well.
|
# be searched for input files as well.
|
||||||
# The default value is: NO.
|
# The default value is: NO.
|
||||||
|
|
||||||
RECURSIVE = YES
|
RECURSIVE = NO
|
||||||
|
|
||||||
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
# The EXCLUDE tag can be used to specify files and/or directories that should be
|
||||||
# excluded from the INPUT source files. This way you can easily exclude a
|
# excluded from the INPUT source files. This way you can easily exclude a
|
||||||
@@ -1035,7 +1036,7 @@ GENERATE_HTML = YES
|
|||||||
# The default directory is: html.
|
# The default directory is: html.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_OUTPUT = documentation/html
|
HTML_OUTPUT = html/doxygen
|
||||||
|
|
||||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||||
# generated HTML page (for example: .htm, .php, .asp).
|
# generated HTML page (for example: .htm, .php, .asp).
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# Version number for the PVA Client API and shared library
|
||||||
|
|
||||||
|
EPICS_PVACLIENT_MAJOR_VERSION = 4
|
||||||
|
EPICS_PVACLIENT_MINOR_VERSION = 7
|
||||||
|
EPICS_PVACLIENT_MAINTENANCE_VERSION = 1
|
||||||
|
|
||||||
|
# Development flag, set to zero for release versions
|
||||||
|
|
||||||
|
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 0
|
||||||
|
|
||||||
|
# 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
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
|
CFG += CONFIG_PVACLIENT_VERSION
|
||||||
|
|
||||||
TARGETS = $(CONFIG_TARGETS)
|
TARGETS = $(CONFIG_TARGETS)
|
||||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,26 @@
|
|||||||
# pvaClientCPP Module
|
pwd# pvaClientCPP Module
|
||||||
|
|
||||||
This document summarizes the changes to the module between releases.
|
This document summarizes the changes to the module between releases.
|
||||||
|
|
||||||
|
## 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)
|
## 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.
|
Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray.
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: #18334B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search input[type="text"] {
|
||||||
|
border-color: #18334b;
|
||||||
|
}
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# http://www.sphinx-doc.org/en/master/config
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
# import sys
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'normativeTypes (C++)'
|
||||||
|
copyright = '2019, EPICS Controls.'
|
||||||
|
author = 'EPICS'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# Intersphinx links to subprojects
|
||||||
|
intersphinx_mapping = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
html_css_files = [
|
||||||
|
'css/custom.css',
|
||||||
|
]
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
html_theme_options = {
|
||||||
|
'logo_only': True,
|
||||||
|
}
|
||||||
|
html_logo = "images/EPICS_white_logo_v02.png"
|
||||||
|
|
||||||
|
html_extra_path = [
|
||||||
|
'../html',
|
||||||
|
'pvaClientCPP.html',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Run Doxygen ------------------------------------------------------------
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
@@ -0,0 +1,17 @@
|
|||||||
|
pvaClient (C++) Library
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
EPICS Website <https://epics-controls.org>
|
||||||
|
EPICS Documentation Home <https://docs.epics-controls.org>
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: pvaClientCPP
|
||||||
|
|
||||||
|
Reference Manual <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/pvaClientCPP.html>
|
||||||
|
API Documentation <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/doxygen>
|
||||||
|
Source Code Repository on GitHub <https://github.com/epics-base/pvaClientCPP>
|
||||||
+1
-1
@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG
|
|||||||
LIBRARY += pvaClient
|
LIBRARY += pvaClient
|
||||||
|
|
||||||
# shared library ABI version.
|
# shared library ABI version.
|
||||||
SHRLIB_VERSION ?= 4.5.0
|
SHRLIB_VERSION ?= $(EPICS_PVACLIENT_MAJOR_VERSION).$(EPICS_PVACLIENT_MINOR_VERSION).$(EPICS_PVACLIENT_MAINTENANCE_VERSION)
|
||||||
|
|
||||||
INC += pv/pvaClient.h
|
INC += pv/pvaClient.h
|
||||||
INC += pv/pvaClientMultiChannel.h
|
INC += pv/pvaClientMultiChannel.h
|
||||||
|
|||||||
+36
-3
@@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/requester.h>
|
#include <pv/requester.h>
|
||||||
#include <pv/status.h>
|
#include <pv/status.h>
|
||||||
@@ -35,7 +36,7 @@
|
|||||||
|
|
||||||
#ifdef pvaClientEpicsExportSharedSymbols
|
#ifdef pvaClientEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef pvaClientEpicsExportSharedSymbols
|
# undef pvaClientEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
@@ -613,6 +614,7 @@ public:
|
|||||||
void setData(
|
void setData(
|
||||||
epics::pvData::PVStructurePtr const & pvStructureFrom,
|
epics::pvData::PVStructurePtr const & pvStructureFrom,
|
||||||
epics::pvData::BitSetPtr const & bitSetFrom);
|
epics::pvData::BitSetPtr const & bitSetFrom);
|
||||||
|
|
||||||
/** @brief Is there a top level field named value.
|
/** @brief Is there a top level field named value.
|
||||||
* @return The answer.
|
* @return The answer.
|
||||||
*/
|
*/
|
||||||
@@ -679,6 +681,29 @@ public:
|
|||||||
* @return The timeStamp.
|
* @return The timeStamp.
|
||||||
*/
|
*/
|
||||||
epics::pvData::TimeStamp getTimeStamp();
|
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
|
||||||
|
*
|
||||||
|
* @param strm output stream
|
||||||
|
* @param ignoreUnprintable false or true; default is true.
|
||||||
|
* @param multiline false or true; 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();
|
||||||
/** @brief Factory method for creating an instance of PvaClientData.
|
/** @brief Factory method for creating an instance of PvaClientData.
|
||||||
*
|
*
|
||||||
* NOTE: Not normally called by clients
|
* NOTE: Not normally called by clients
|
||||||
@@ -688,15 +713,23 @@ public:
|
|||||||
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
|
||||||
protected:
|
protected:
|
||||||
PvaClientData(epics::pvData::StructureConstPtr const & structure);
|
PvaClientData(epics::pvData::StructureConstPtr const & structure);
|
||||||
|
epics::pvData::PVFieldPtr getSinglePVField();
|
||||||
void checkValue();
|
void checkValue();
|
||||||
std::string messagePrefix;
|
std::string messagePrefix;
|
||||||
private:
|
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::StructureConstPtr structure;
|
||||||
epics::pvData::PVStructurePtr pvStructure;
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
epics::pvData::BitSetPtr bitSet;
|
epics::pvData::BitSetPtr bitSet;
|
||||||
|
|
||||||
|
|
||||||
epics::pvData::PVFieldPtr pvValue;
|
epics::pvData::PVFieldPtr pvValue;
|
||||||
epics::pvData::PVAlarm pvAlarm;
|
epics::pvData::PVAlarm pvAlarm;
|
||||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||||
@@ -1813,6 +1846,7 @@ private:
|
|||||||
|
|
||||||
enum RPCState {rpcIdle,rpcActive,rpcComplete};
|
enum RPCState {rpcIdle,rpcActive,rpcComplete};
|
||||||
RPCState rpcState;
|
RPCState rpcState;
|
||||||
|
epics::pvData::Status requestStatus;
|
||||||
double responseTimeout;
|
double responseTimeout;
|
||||||
friend class RPCRequesterImpl;
|
friend class RPCRequesterImpl;
|
||||||
};
|
};
|
||||||
@@ -1826,4 +1860,3 @@ private:
|
|||||||
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
|
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
|
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef pvaClientMultiChannelEpicsExportSharedSymbols
|
# undef pvaClientMultiChannelEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -360,8 +360,10 @@ public:
|
|||||||
void connect();
|
void connect();
|
||||||
/**
|
/**
|
||||||
* @brief Get each channel.
|
* @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.
|
* @brief Get the data from the last get.
|
||||||
* @return the pvaClientNTMultiData.
|
* @return the pvaClientNTMultiData.
|
||||||
@@ -476,10 +478,11 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Poll each channel.
|
* @brief Poll each channel.
|
||||||
*
|
*
|
||||||
|
* @param valueOnly use only value for union.
|
||||||
* If any has new data it is used to update the double[].
|
* If any has new data it is used to update the double[].
|
||||||
* @return (false,true) if (no, at least one) value was updated.
|
* @return (false,true) if (no, at least one) value was updated.
|
||||||
*/
|
*/
|
||||||
bool poll();
|
bool poll(bool valueOnly = true);
|
||||||
/**
|
/**
|
||||||
* @brief Wait until poll returns true.
|
* @brief Wait until poll returns true.
|
||||||
* @param secondsToWait The time to keep trying.
|
* @param secondsToWait The time to keep trying.
|
||||||
@@ -551,11 +554,12 @@ public:
|
|||||||
* @brief Set the timeStamp base for computing deltaTimes.
|
* @brief Set the timeStamp base for computing deltaTimes.
|
||||||
*/
|
*/
|
||||||
void startDeltaTime();
|
void startDeltaTime();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update NTMultiChannel fields.
|
* @brief Update NTMultiChannel fields.
|
||||||
|
*
|
||||||
|
* @param valueOnly use only value for union.
|
||||||
*/
|
*/
|
||||||
void endDeltaTime();
|
void endDeltaTime(bool valueOnly = true);
|
||||||
/**
|
/**
|
||||||
* @brief Get the time when the last get was made.
|
* @brief Get the time when the last get was made.
|
||||||
* @return The timeStamp.
|
* @return The timeStamp.
|
||||||
@@ -579,7 +583,6 @@ private:
|
|||||||
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
|
||||||
PvaClientChannelArray const &pvaClientChannelArray,
|
PvaClientChannelArray const &pvaClientChannelArray,
|
||||||
epics::pvData::PVStructurePtr const & pvRequest);
|
epics::pvData::PVStructurePtr const & pvRequest);
|
||||||
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
|
|
||||||
void setPVStructure(
|
void setPVStructure(
|
||||||
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
|
||||||
|
|
||||||
@@ -612,4 +615,3 @@ private:
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* PVACLIENTMULTICHANNEL_H */
|
#endif /* PVACLIENTMULTICHANNEL_H */
|
||||||
|
|
||||||
|
|||||||
@@ -231,4 +231,3 @@ size_t PvaClient::cacheSize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
+191
-112
@@ -11,9 +11,17 @@
|
|||||||
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <istream>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
#include <pv/createRequest.h>
|
#include <pv/createRequest.h>
|
||||||
#include <pv/convert.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
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
@@ -49,6 +57,30 @@ PvaClientData::PvaClientData(StructureConstPtr const & 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()
|
void PvaClientData::checkValue()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
|
||||||
@@ -106,6 +138,7 @@ void PvaClientData::setData(
|
|||||||
pvValue = pvStructure->getSubField("value");
|
pvValue = pvStructure->getSubField("value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PvaClientData::hasValue()
|
bool PvaClientData::hasValue()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
|
||||||
@@ -171,34 +204,12 @@ PVScalarArrayPtr PvaClientData::getScalarArrayValue()
|
|||||||
double PvaClientData::getDouble()
|
double PvaClientData::getDouble()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
|
||||||
PVScalarPtr pvScalar;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalar) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getDouble() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalar) {
|
|
||||||
pvScalar = static_pointer_cast<PVScalar>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getDouble() did not find a scalar field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||||
if(scalarType==pvDouble) {
|
if(scalarType==pvDouble) {
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
||||||
@@ -214,70 +225,24 @@ double PvaClientData::getDouble()
|
|||||||
string PvaClientData::getString()
|
string PvaClientData::getString()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
|
||||||
PVScalarPtr pvScalar;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalar) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::getString() did not find a scalar field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getString() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalar) {
|
|
||||||
pvScalar = static_pointer_cast<PVScalar>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getString() did not find a scalar field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
return convert->toString(pvScalar);
|
return convert->toString(pvScalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_vector<const double> PvaClientData::getDoubleArray()
|
shared_vector<const double> PvaClientData::getDoubleArray()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
|
||||||
PVScalarArrayPtr pvScalarArray;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalarArray) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getDoubleArray() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getDoubleArray() did not find a scalarArray field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
@@ -291,36 +256,12 @@ shared_vector<const double> PvaClientData::getDoubleArray()
|
|||||||
shared_vector<const string> PvaClientData::getStringArray()
|
shared_vector<const string> PvaClientData::getStringArray()
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
|
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
|
||||||
PVScalarArrayPtr pvScalarArray;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalarArray) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getStringArray() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::getStringArray() did not find a scalarArray field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
shared_vector<const string> retValue;
|
shared_vector<const string> retValue;
|
||||||
pvScalarArray->getAs<const string>(retValue);
|
pvScalarArray->getAs<const string>(retValue);
|
||||||
return retValue;
|
return retValue;
|
||||||
@@ -358,4 +299,142 @@ TimeStamp PvaClientData::getTimeStamp()
|
|||||||
throw std::runtime_error(messagePrefix + noTimeStamp);
|
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 epics::pvData::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 epics::pvData::scalarArray:
|
||||||
|
{
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
pvScalarArray->setLength(0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case epics::pvData::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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ Status PvaClientMultiChannel::connect(double timeout)
|
|||||||
Status status = Status::Ok;
|
Status status = Status::Ok;
|
||||||
size_t numBad = 0;
|
size_t numBad = 0;
|
||||||
for(size_t i=0; i< numChannel; ++i) {
|
for(size_t i=0; i< numChannel; ++i) {
|
||||||
if(numBad==0) {
|
if(numBad==0) {
|
||||||
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
status = pvaClientChannelArray[i]->waitConnect(timeout);
|
||||||
} else {
|
} else {
|
||||||
status = pvaClientChannelArray[i]->waitConnect(.001);
|
status = pvaClientChannelArray[i]->waitConnect(.001);
|
||||||
|
|||||||
@@ -44,10 +44,6 @@ PvaClientNTMultiData::PvaClientNTMultiData(
|
|||||||
gotTimeStamp(false)
|
gotTimeStamp(false)
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
|
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
|
||||||
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
|
|
||||||
if(!pvValue) {
|
|
||||||
throw std::runtime_error("pvRequest did not specify value");
|
|
||||||
}
|
|
||||||
topPVStructure.resize(nchannel);
|
topPVStructure.resize(nchannel);
|
||||||
unionValue.resize(nchannel);
|
unionValue.resize(nchannel);
|
||||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
@@ -88,18 +84,6 @@ PvaClientNTMultiData::~PvaClientNTMultiData()
|
|||||||
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
|
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(
|
void PvaClientNTMultiData::setPVStructure(
|
||||||
PVStructurePtr const &pvStructure,size_t index)
|
PVStructurePtr const &pvStructure,size_t index)
|
||||||
{
|
{
|
||||||
@@ -137,7 +121,7 @@ void PvaClientNTMultiData::startDeltaTime()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PvaClientNTMultiData::endDeltaTime()
|
void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
|
||||||
{
|
{
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
@@ -145,18 +129,41 @@ void PvaClientNTMultiData::endDeltaTime()
|
|||||||
if(!pvst) {
|
if(!pvst) {
|
||||||
unionValue[i] = PVUnionPtr();
|
unionValue[i] = PVUnionPtr();
|
||||||
} else if(unionValue[i]) {
|
} else if(unionValue[i]) {
|
||||||
unionValue[i]->set(pvst->getSubField("value"));
|
if(valueOnly) {
|
||||||
|
PVFieldPtr pvValue = pvst->getSubField("value");
|
||||||
|
if(pvValue) {
|
||||||
|
unionValue[i]->set(pvst->getSubField("value"));
|
||||||
|
} else {
|
||||||
|
unionValue[i] = PVUnionPtr();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unionValue[i]->set(pvst);
|
||||||
|
}
|
||||||
if(gotAlarm)
|
if(gotAlarm)
|
||||||
{
|
{
|
||||||
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
|
PVIntPtr pvSeverity = pvst->getSubField<PVInt>("alarm.severity");
|
||||||
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
|
PVIntPtr pvStatus = pvst->getSubField<PVInt>("alarm.status");
|
||||||
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
|
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)
|
if(gotTimeStamp)
|
||||||
{
|
{
|
||||||
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
|
PVLongPtr pvEpoch = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch");
|
||||||
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
|
PVIntPtr pvNano = pvst->getSubField<PVInt>("timeStamp.nanoseconds");
|
||||||
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
|
PVIntPtr pvTag = pvst->getSubField<PVInt>("timeStamp.userTag");
|
||||||
|
if(pvEpoch&&pvNano&&pvTag) {
|
||||||
|
secondsPastEpoch[i] = pvEpoch->get();
|
||||||
|
nanoseconds[i] = pvNano->get();
|
||||||
|
userTag[i] = pvTag->get();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,13 +63,10 @@ void PvaClientNTMultiGet::connect()
|
|||||||
{
|
{
|
||||||
pvaClientGet.resize(nchannel);
|
pvaClientGet.resize(nchannel);
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
string request = "value";
|
|
||||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
|
||||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
|
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
|
||||||
pvaClientGet[i]->issueConnect();
|
pvaClientGet[i]->issueConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -86,7 +83,7 @@ void PvaClientNTMultiGet::connect()
|
|||||||
this->isConnected = true;
|
this->isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientNTMultiGet::get()
|
void PvaClientNTMultiGet::get(bool valueOnly)
|
||||||
{
|
{
|
||||||
if(!isConnected) connect();
|
if(!isConnected) connect();
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
@@ -114,7 +111,7 @@ void PvaClientNTMultiGet::get()
|
|||||||
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pvaClientNTMultiData->endDeltaTime();
|
pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
|
||||||
|
|||||||
@@ -67,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
|
|||||||
{
|
{
|
||||||
pvaClientMonitor.resize(nchannel);
|
pvaClientMonitor.resize(nchannel);
|
||||||
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
|
||||||
string request = "value";
|
|
||||||
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
|
|
||||||
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
|
|
||||||
for(size_t i=0; i<nchannel; ++i)
|
for(size_t i=0; i<nchannel; ++i)
|
||||||
{
|
{
|
||||||
if(isConnected[i]) {
|
if(isConnected[i]) {
|
||||||
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
|
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
|
||||||
pvaClientMonitor[i]->issueConnect();
|
pvaClientMonitor[i]->issueConnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,7 +91,7 @@ void PvaClientNTMultiMonitor::connect()
|
|||||||
this->isConnected = true;
|
this->isConnected = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PvaClientNTMultiMonitor::poll()
|
bool PvaClientNTMultiMonitor::poll(bool valueOnly)
|
||||||
{
|
{
|
||||||
if(!isConnected) connect();
|
if(!isConnected) connect();
|
||||||
bool result = false;
|
bool result = false;
|
||||||
@@ -111,7 +108,7 @@ bool PvaClientNTMultiMonitor::poll()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(result) pvaClientNTMultiData->endDeltaTime();
|
if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-112
@@ -74,34 +74,12 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
|
|||||||
void PvaClientPutData::putDouble(double value)
|
void PvaClientPutData::putDouble(double value)
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
|
||||||
PVScalarPtr pvScalar;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalar) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::putDouble() did not find a scalar field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putDouble() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalar) {
|
|
||||||
pvScalar = static_pointer_cast<PVScalar>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putDouble() did not find a scalar field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
|
||||||
if(scalarType==pvDouble) {
|
if(scalarType==pvDouble) {
|
||||||
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
|
||||||
@@ -118,70 +96,24 @@ void PvaClientPutData::putDouble(double value)
|
|||||||
void PvaClientPutData::putString(std::string const & value)
|
void PvaClientPutData::putString(std::string const & value)
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
|
||||||
PVScalarPtr pvScalar;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalar) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::putString() did not find a scalar field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putString() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalar) {
|
|
||||||
pvScalar = static_pointer_cast<PVScalar>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalar) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putString() did not find a scalar field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
|
||||||
convert->fromString(pvScalar,value);
|
convert->fromString(pvScalar,value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
|
||||||
PVScalarArrayPtr pvScalarArray;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalarArray) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::putDoubleArray() did not find a scalarArray field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putDoubleArray() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putDoubleArray() did not find a scalarArray field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
|
||||||
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
if(!ScalarTypeFunc::isNumeric(scalarType)) {
|
||||||
throw std::logic_error(
|
throw std::logic_error(
|
||||||
@@ -193,36 +125,12 @@ void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
|
|||||||
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
|
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
|
||||||
{
|
{
|
||||||
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
|
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
|
||||||
PVScalarArrayPtr pvScalarArray;
|
PVFieldPtr pvField = getSinglePVField();
|
||||||
PVStructurePtr pvStructure = getPVStructure();
|
Type type = pvField->getField()->getType();
|
||||||
PVFieldPtr pvValue = pvStructure->getSubField("value");
|
if(type!=scalarArray) {
|
||||||
if(pvValue) {
|
throw std::logic_error("PvaClientData::putStringArray() did not find a scalarArray field");
|
||||||
Type type = pvValue->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
while(true) {
|
|
||||||
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
|
|
||||||
if(fieldPtrArray.size()!=1) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putStringArray() pvRequest for multiple fields");
|
|
||||||
}
|
|
||||||
PVFieldPtr pvField(fieldPtrArray[0]);
|
|
||||||
Type type = pvField->getField()->getType();
|
|
||||||
if(type==scalarArray) {
|
|
||||||
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(pvField->getField()->getType()!=epics::pvData::structure) break;
|
|
||||||
pvStructure = static_pointer_cast<PVStructure>(pvField);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!pvScalarArray) {
|
|
||||||
throw std::logic_error(
|
|
||||||
"PvaClientData::putStringArray() did not find a scalarArray field");
|
|
||||||
}
|
}
|
||||||
|
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
pvScalarArray->putFrom<const string>(value);
|
pvScalarArray->putFrom<const string>(value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-3
@@ -12,6 +12,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <pv/event.h>
|
#include <pv/event.h>
|
||||||
#include <pv/bitSetUtil.h>
|
#include <pv/bitSetUtil.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
|
||||||
@@ -180,6 +181,7 @@ void PvaClientRPC::requestDone(
|
|||||||
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
|
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
|
requestStatus = status;
|
||||||
if(PvaClient::getDebug()) {
|
if(PvaClient::getDebug()) {
|
||||||
string channelName("disconnected");
|
string channelName("disconnected");
|
||||||
Channel::shared_pointer chan(channel.lock());
|
Channel::shared_pointer chan(channel.lock());
|
||||||
@@ -224,7 +226,7 @@ void PvaClientRPC::connect()
|
|||||||
+ channelName
|
+ channelName
|
||||||
+ " PvaClientRPC::connect "
|
+ " PvaClientRPC::connect "
|
||||||
+ status.getMessage();
|
+ status.getMessage();
|
||||||
throw std::runtime_error(message);
|
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PvaClientRPC::issueConnect()
|
void PvaClientRPC::issueConnect()
|
||||||
@@ -305,10 +307,18 @@ PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer co
|
|||||||
string message = "channel "
|
string message = "channel "
|
||||||
+ channelName
|
+ channelName
|
||||||
+ " PvaClientRPC::request request timeout ";
|
+ " PvaClientRPC::request request timeout ";
|
||||||
throw std::runtime_error(message);
|
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
|
||||||
}
|
}
|
||||||
rpcState = rpcIdle;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user