All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cosylab.epics.caj.cas.handlers.AbstractCASResponseHandler Maven / Gradle / Ivy

Go to download

JCA is an EPICS Channel Access library for Java. For more information concerning EPICS or Channel Access please refer to the <a href="http://www.aps.anl.gov/epics">EPICS Web pages</a> or read the <a href="http://www.aps.anl.gov/epics/base/R3-14/8-docs/CAref.html">Channel Access manual (3.14)</a>. <p>This module also includes CAJ, A 100% pure Java implementation of the EPICS Channel Access library.</p>

There is a newer version: 2.4.10
Show newest version
/*
 * Copyright (c) 2004 by Cosylab
 *
 * The full license specifying the redistribution, modification, usage and other
 * rights and obligations is included with the distribution of this project in
 * the file "LICENSE-CAJ". If the license is not included visit Cosylab web site,
 * .
 *
 * THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY OF ANY KIND, NOT EVEN THE
 * IMPLIED WARRANTY OF MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE, ASSUMES
 * _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE RESULTING FROM THE USE, MODIFICATION,
 * OR REDISTRIBUTION OF THIS SOFTWARE.
 */

package com.cosylab.epics.caj.cas.handlers;

import gov.aps.jca.CAStatus;
import gov.aps.jca.cas.ProcessVariable;
import gov.aps.jca.dbr.DBR;
import gov.aps.jca.dbr.DBRFactory;
import gov.aps.jca.dbr.DBRType;
import gov.aps.jca.dbr.DBR_PRECISION_Double;
import gov.aps.jca.dbr.DBR_PRECISION_Float;
import gov.aps.jca.dbr.DBR_TIME_LABELS_Enum;
import gov.aps.jca.dbr.PRECISION;
import gov.aps.jca.dbr.STS;
import gov.aps.jca.dbr.Severity;
import gov.aps.jca.dbr.Status;

import java.nio.ByteBuffer;
import java.util.logging.Level;

import com.cosylab.epics.caj.cas.CAJServerContext;
import com.cosylab.epics.caj.cas.requests.ExceptionRequest;
import com.cosylab.epics.caj.impl.Transport;
import com.cosylab.epics.caj.impl.handlers.AbstractCAResponseHandler;

/**
 * @author Matej Sekoranja
 * @version $id$
 */
public abstract class AbstractCASResponseHandler extends AbstractCAResponseHandler {

	/**
	 * Context instance.
	 */
	protected CAJServerContext context;

	/**
	 * @param context
	 * @param description
	 */
	public AbstractCASResponseHandler(CAJServerContext context, String description) {
		super(description);
		this.context = context;
	}

	/**
	 * Extract string from payload.
	 * @param buffer buffer to use.
	 * @param start buffer offset to use, if negative current buffer position will be used
	 * @param maxSize maximum payload size reserved for string.
	 * @param setToEnd set to the end of string flag (after zero char)
	 * @return extracted string.
	 */
	public static final String extractString(ByteBuffer buffer, int start, int maxSize, boolean setToEnd)
	{
		if (start < 0)
			start = buffer.position();
		final int bufferEnd = start + maxSize;

		byte[] data = buffer.array();
		int end = start;
		
		// find zero char (string terminator)
		while (data[end] != 0 && end < bufferEnd)
			end++;

		// set to the end
		if (setToEnd && end != bufferEnd)
			buffer.position(end + 1); // skip 0 character
		
		return new String(data, start, end-start);
	}

	/**
	 * Send error (exception) response.
	 * @param transport	transport to use.
	 * @param cid channel ID.
	 * @param errorStatus error status.
	 * @param previousHeader header of the request messages causing this error.
	 * @param message string message, can be null.
	 */
	protected void sendException(Transport transport, int cid, 
			CAStatus errorStatus, ByteBuffer previousHeader, String message)
	{
		try {
			// prepare for reading
			previousHeader.flip();

			new ExceptionRequest(transport,	cid, errorStatus, previousHeader, message).submit();
		} catch (Throwable th) {
			context.getLogger().log(Level.WARNING, "Failed to send exception response for CID: " + cid, th);
		}
	}

	
	
	// type value codes
	private static final int DBR_TIME_OFFSET = 14;
	private static final int DBR_GR_OFFSET = 21;
	private static final int DBR_CTRL_OFFSET = 28;

	/**
	 * Create appropriate DBR structure for reading (of PV type).
	 * Returned DBR structure will be the most complete one (CTRL usually)., PV array length.
	 * @param processVariable	process variable to be read.
	 * @return requested DBR.
	 */
	public static final DBR createDBRforReading(ProcessVariable processVariable)
	{
		return createDBRforReading(processVariable, processVariable.getDimensionSize(0));
	}
	
	/**
	 * Create appropriate DBR structure for reading (of PV type).
	 * Returned DBR structure will be the most complete one (CTRL usually).
	 * @param processVariable	process variable to be read.
	 * @param dataCount	requested data count (returned DBR will have this count).
	 * @return requested DBR.
	 */
	public static final DBR createDBRforReading(ProcessVariable processVariable, int dataCount)
	{
		return createDBRforReading(processVariable, (short)DBR_CTRL_OFFSET, dataCount);
	}
	
		/**
	 * Create appropriate DBR structure for reading (of PV type).
	 * @param processVariable	process variable to be read.
	 * @param dataType 	data type requested from client (not necessary equals to PV type)
	 * @param dataCount	requested data count (returned DBR will have this count).
	 * @return requested DBR.
	 */
	public static final DBR createDBRforReading(ProcessVariable processVariable, short dataType, int dataCount)
	{

		// get native type (plain type) and convert it to TIME type (or GR, CTRL if requested)
		int offset = DBR_TIME_OFFSET;
		if (dataType >= DBR_GR_OFFSET)
			offset = (dataType >= DBR_CTRL_OFFSET) ? DBR_CTRL_OFFSET : DBR_GR_OFFSET;

		// calculate new type
		DBRType type = processVariable.getType();
		int typeValue = type.getValue() + offset;
		
		DBR value;
		
		// special case for TIME_Double, TIME_Float
		// use an "artificial" TIME type with PRECISION
		// they are needed for string formatting
		if (typeValue == 20)
			value = new DBR_PRECISION_Double(dataCount);
		else if (typeValue == 16)
			value = new DBR_PRECISION_Float(dataCount);
		// special case to get the enum table, TIME_Enum -> LABELS_Enum
		// use an "artificial" DBR_TIME_LABELS type to support timestamping 
		else if (typeValue == 17 || typeValue == 24 || typeValue == 31 )
			value = new DBR_TIME_LABELS_Enum(dataCount);
		else
		{
			type = DBRType.forValue(typeValue);
	
			// create native DBR_{TIME, GR, CTRL}_ and set default values
			// use required count
			value = DBRFactory.create(type, dataCount);
		}
		
		// set undefined status
		STS dbrSts = (STS)value;
		dbrSts.setSeverity(Severity.INVALID_ALARM);
		dbrSts.setStatus(Status.UDF_ALARM);
		
		// initialize precision 
		if (value.isPRECSION())
			((PRECISION)value).setPrecision((short)-1);

		return value;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy