001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: crawl $'
006 * '$Date: 2015-08-24 22:48:48 +0000 (Mon, 24 Aug 2015) $' 
007 * '$Revision: 33634 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030package org.ROADnet;
031
032import com.brtt.antelope.Orb;
033import com.brtt.antelope.OrbErrorException;
034import com.brtt.antelope.OrbPacketChannel;
035import com.brtt.antelope.OrbWaveformPacket;
036import com.brtt.antelope.SourceName;
037
038import ptolemy.actor.TypedAtomicActor;
039import ptolemy.actor.TypedIOPort;
040import ptolemy.data.DoubleToken;
041import ptolemy.data.IntToken;
042import ptolemy.data.StringToken;
043import ptolemy.data.expr.Parameter;
044import ptolemy.data.type.BaseType;
045import ptolemy.kernel.CompositeEntity;
046import ptolemy.kernel.util.IllegalActionException;
047import ptolemy.kernel.util.NameDuplicationException;
048
049/**
050 * Ptolemy actor to send waveform data to an Antelope ORB
051 * 
052 * @author Tobin Fricke, University of California
053 * @version $Id: OrbWaveformSink.java 33634 2015-08-24 22:48:48Z crawl $
054 * @Pt.ProposedRating Red (tobin)
055 */
056
057public class OrbWaveformSink extends TypedAtomicActor {
058
059        /**
060         * @param container
061         *            The container.
062         * @param name
063         *            The name of this actor.
064         * @exception IllegalActionException
065         *                If the actor cannot be contained by the proposed
066         *                container.
067         * @exception NameDuplicationException
068         *                If the container already has an actor with this name.
069         */
070
071        public OrbWaveformSink(CompositeEntity container, String name)
072                        throws NameDuplicationException, IllegalActionException {
073                super(container, name);
074
075                input = new TypedIOPort(this, "input", true, false);
076                times = new TypedIOPort(this, "times", true, false);
077
078                input.setMultiport(false);
079                input.setTypeEquals(BaseType.INT);
080
081                times.setMultiport(false);
082                times.setTypeEquals(BaseType.DOUBLE);
083
084                orbname = new Parameter(this, "orbname");
085                srcname = new Parameter(this, "srcname");
086                nsamp = new Parameter(this, "nsamp");
087                samprate = new Parameter(this, "samprate");
088
089                orbname.setTypeEquals(BaseType.STRING);
090                srcname.setTypeEquals(BaseType.STRING);
091        }
092
093        /* The initialization will connect to the ORB */
094
095        public void initialize() throws IllegalActionException {
096                System.out.println("OrbWaveformSink: initialize");
097                try {
098                        super.initialize();
099                        _orb = new Orb(StringToken.convert(orbname.getToken())
100                                        .stringValue(), "w");
101                        _orb.select(StringToken.convert(srcname.getToken()).stringValue());
102                        _orb.after(0);
103                } catch (Exception e) {
104                        System.out.println("Couldn't connect to ORB! (" + e + ")");
105                }
106        }
107
108        public boolean prefire() throws IllegalActionException {
109                return (input.hasToken(0) && super.prefire());
110        }
111
112        public void fire() throws IllegalActionException {
113                super.fire();
114                try {
115
116                        int nsamp = ((IntToken) (this.nsamp.getToken())).intValue();
117
118                        /*
119                         * We expect timestamps to arrive synchronously with samples. We
120                         * only keep the timestamps that correspond to the beginning of a
121                         * packet, however.
122                         */
123
124                        double sampleTime = ((DoubleToken) (times.get(0))).doubleValue();
125
126                        /*
127                         * Manufacture a new array for each packet, since OrbPacket doesn't
128                         * (currently) make a copy. Not sure if this is necessary.
129                         */
130
131                        if (samplesSoFar == 0) {
132                                samplesBuffer = new int[nsamp];
133                                packetTime = sampleTime;
134                        }
135
136                        samplesBuffer[samplesSoFar] = ((IntToken) (input.get(0)))
137                                        .intValue();
138                        samplesSoFar++;
139
140                        if (samplesSoFar == nsamp) {
141
142                                samplesSoFar = 0;
143
144                                String srcname = ((StringToken) (this.srcname.getToken()))
145                                                .stringValue();
146
147                                double samprate = ((DoubleToken) (this.samprate.getToken()))
148                                                .doubleValue();
149
150                                OrbWaveformPacket pkt = new OrbWaveformPacket(packetTime, 0,
151                                                new SourceName(srcname));
152
153                                double calib = 1.0; // FixMe
154                                double calper = -1;
155                                String segtype = "c";
156
157                                OrbPacketChannel channel = new OrbPacketChannel(samplesBuffer,
158                                                pkt.srcname, calib, calper, segtype, packetTime,
159                                                samprate);
160
161                                pkt.addChannel(channel);
162                                // pkt.stuffGEN();
163
164                                System.out.println("Pushing this channel:\"" + channel + "\"");
165                                System.out.println("In this packet: \"" + pkt + "\"");
166                                _orb.put(pkt.stuff());
167
168                        }
169
170                } catch (java.io.IOException e) {
171                        // hmm -- what is the best thing to do here?
172                        System.out
173                                        .println("OrbWaveformSink: fire() experienced IOexception: "
174                                                        + e);
175                } catch (OrbErrorException e) {
176                        System.out
177                                        .println("OrbWaveformSink: fire() experienced OrbErrorException: "
178                                                        + e);
179                }
180
181        }
182
183        /**
184         * The name of the orb to connect to, in the format "hostname:port". Note
185         * that orbnames.pf-style names are not supported -- you have to use a valid
186         * IP address or resolvable DNS name, and you have to use a numeric port
187         * number.
188         */
189        public Parameter orbname;
190        /**
191         * The source name to request from the Orb. When this actor is initialized,
192         * orb.select() is called with the value of this parameter.
193         */
194        public Parameter srcname;
195        /** The number of samples per packet. */
196        public Parameter nsamp; // number of samples per packet
197        /** The rate at which samples are being updated/entering in the packet */
198        public Parameter samprate;
199        /** Data values to be written to the Antelope ORB */
200        public TypedIOPort input;
201        /** The packet time of the ORB stream being written to */
202        public TypedIOPort times;
203
204        private Orb _orb = null;
205        private int samplesBuffer[] = null;
206        private int samplesSoFar = 0;
207        private double packetTime = 0;
208}