History

Added GridSolutionsFramework.sln to source control.

StephenCWills committed 14 years ago

Commit c5f7ca6No parent (first commit)915 files · +335125 −-73Browse files

Showing the changes to Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/AdvancedSubscribe.java (1 of 915 files). Show all

Unified · Split

Source/Libraries/TSFJavaLibrary/src/org/gpa/tsf/sample/AdvancedSubscribe.java+453−0
@@ -0,0 +1,453 @@
1+//******************************************************************************************************
2+// AdvancedSubscribe.java - Gbtc
3+//
4+// Copyright � 2010, Grid Protection Alliance. All Rights Reserved.
5+//
6+// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
7+// the NOTICE file distributed with this work for additional information regarding copyright ownership.
8+// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
9+// not use this file except in compliance with the License. You may obtain a copy of the License at:
10+//
11+// http://www.opensource.org/licenses/eclipse-1.0.php
12+//
13+// Unless agreed to in writing, the subject software distributed under the License is distributed on an
14+// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
15+// License for the specific language governing permissions and limitations.
16+//
17+// Code Modification History:
18+// ----------------------------------------------------------------------------------------------------
19+// 04/23/2012 - Stephen C. Wills
20+// Generated original version of source code.
21+//
22+//******************************************************************************************************
23+
24+package org.gpa.tsf.sample;
25+
26+import java.awt.GridBagConstraints;
27+import java.awt.GridBagLayout;
28+import java.awt.event.ActionEvent;
29+import java.awt.event.ActionListener;
30+import java.io.IOException;
31+import java.io.OutputStream;
32+import java.io.PrintStream;
33+import java.net.SocketException;
34+import java.nio.ByteBuffer;
35+import java.nio.charset.Charset;
36+
37+import javax.swing.Box;
38+import javax.swing.BoxLayout;
39+import javax.swing.JApplet;
40+import javax.swing.JButton;
41+import javax.swing.JLabel;
42+import javax.swing.JScrollPane;
43+import javax.swing.JTextArea;
44+import javax.swing.JTextField;
45+import javax.swing.SwingUtilities;
46+
47+import org.gpa.tsf.transport.DataSubscriber;
48+import org.gpa.tsf.transport.SubscriberConnector;
49+import org.gpa.tsf.transport.SubscriptionInfo;
50+import org.gpa.tsf.transport.event.SubscriberConnectorListener;
51+
52+/**
53+ * Sample applet to demonstrate the more advanced use of the subscriber API.
54+ *
55+ * This application accepts the hostname and port of the publisher via text
56+ * fields on the applet, connects to the publisher, subscribes, and displays
57+ * information about the measurements it receives. It assumes that the
58+ * publisher is providing fourteen measurements (PPA:1 through PPA:14) and
59+ * will retry infinitely if it has any trouble connecting. It will also
60+ * automatically reconnect if the connection is terminated.
61+ *
62+ * Measurements are transmitted via a separate UDP data channel.
63+ */
64+public class AdvancedSubscribe extends JApplet
65+{
66+ private Object m_connectLock;
67+ private ActionListener m_connectListener;
68+ private ActionListener m_disconnectListener;
69+
70+ private JScrollPane m_outputScrollPane;
71+ private JTextArea m_outputTextArea;
72+ private JLabel m_hostnameLabel;
73+ private JLabel m_portLabel;
74+ private JTextField m_hostnameTextField;
75+ private JTextField m_portTextField;
76+ private JButton m_connectButton;
77+ private JButton m_disconnectButton;
78+ private Box m_buttonBox;
79+
80+ private PrintStream m_outputStream;
81+ private SubscriptionInfo m_subscriptionInfo;
82+ private SubscriberConnector m_connector;
83+ private DataSubscriber m_subscriber;
84+
85+ @Override
86+ public void init()
87+ {
88+ GridBagConstraints constraints;
89+
90+ super.init();
91+
92+ // Initialize members
93+ m_connectLock = new Object();
94+ m_connectListener = createConnectListener();
95+ m_disconnectListener = createDisconnectListener();
96+
97+ m_outputTextArea = createOutputTextArea();
98+ m_outputScrollPane = new JScrollPane(m_outputTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
99+ m_hostnameLabel = new JLabel("Hostname");
100+ m_portLabel = new JLabel("Port");
101+ m_hostnameTextField = createHostnameTextField();
102+ m_portTextField = createPortTextField();
103+ m_connectButton = createConnectButton();
104+ m_disconnectButton = createDisconnectButton();
105+ m_buttonBox = createButtonBox();
106+
107+ m_outputStream = createOutputStream();
108+ m_subscriptionInfo = createSubscriptionInfo();
109+ m_connector = createSubscriberConnector(m_subscriptionInfo, m_outputStream);
110+ m_subscriber = createSubscriber();
111+
112+ // Component layout
113+ getContentPane().setLayout(new GridBagLayout());
114+
115+ constraints = new GridBagConstraints();
116+ constraints.fill = GridBagConstraints.BOTH;
117+ constraints.gridwidth = 2;
118+ constraints.weighty = 1.0;
119+ getContentPane().add(m_outputScrollPane, constraints);
120+
121+ constraints = new GridBagConstraints();
122+ constraints.gridy = 1;
123+ constraints.weightx = 0.5;
124+ getContentPane().add(m_hostnameLabel, constraints);
125+
126+ constraints = new GridBagConstraints();
127+ constraints.gridx = 1;
128+ constraints.gridy = 1;
129+ constraints.weightx = 0.5;
130+ getContentPane().add(m_portLabel, constraints);
131+
132+ constraints = new GridBagConstraints();
133+ constraints.fill = GridBagConstraints.HORIZONTAL;
134+ constraints.gridy = 2;
135+ constraints.weightx = 0.5;
136+ getContentPane().add(m_hostnameTextField, constraints);
137+
138+ constraints = new GridBagConstraints();
139+ constraints.fill = GridBagConstraints.HORIZONTAL;
140+ constraints.gridx = 1;
141+ constraints.gridy = 2;
142+ constraints.weightx = 0.5;
143+ getContentPane().add(m_portTextField, constraints);
144+
145+ constraints = new GridBagConstraints();
146+ constraints.anchor = GridBagConstraints.CENTER;
147+ constraints.gridy = 3;
148+ constraints.gridwidth = 2;
149+ getContentPane().add(m_buttonBox, constraints);
150+ }
151+
152+ // Creates the action listener used to connect to the publisher.
153+ private ActionListener createConnectListener()
154+ {
155+ return new ActionListener()
156+ {
157+ @Override
158+ public void actionPerformed(ActionEvent arg0)
159+ {
160+ // Set the hostname and port before attempting to connect
161+ m_connector.setHostname(m_hostnameTextField.getText());
162+ m_connector.setPort(Integer.parseInt(m_portTextField.getText()));
163+
164+ // Connect asynchronously so we don't hog the UI thread
165+ connectAsync();
166+ }
167+ };
168+ }
169+
170+ // Connects and subscribes to the publisher asynchronously.
171+ private void connectAsync()
172+ {
173+ new Thread(new Runnable()
174+ {
175+ @Override
176+ public void run()
177+ {
178+ // Lock the connect lock so we don't encounter
179+ // synchronization issues between calls to connectAsync
180+ // and disconnectAsync
181+ synchronized (m_connectLock)
182+ {
183+ try
184+ {
185+ if (m_connector.connect(m_subscriber))
186+ m_subscriber.subscribe(m_subscriptionInfo);
187+ }
188+ catch (SocketException ex)
189+ {
190+ ex.printStackTrace(m_outputStream);
191+ }
192+ }
193+ }
194+ }).start();
195+ }
196+
197+ // Creates the disconnect listener used to disconnect from the publisher.
198+ private ActionListener createDisconnectListener()
199+ {
200+ return new ActionListener()
201+ {
202+ @Override
203+ public void actionPerformed(ActionEvent arg0)
204+ {
205+ // Disconnect asynchronously so we don't hog the UI thread
206+ disconnectAsync();
207+ }
208+ };
209+ }
210+
211+ // Disconnects from the publisher asynchronously.
212+ private void disconnectAsync()
213+ {
214+ new Thread(new Runnable()
215+ {
216+ @Override
217+ public void run()
218+ {
219+ // Cancel the connector first so it won't try
220+ // to automatically reconnect for any reason
221+ m_connector.cancel();
222+
223+ // Lock the connect lock so we don't encounter
224+ // synchronization issues between calls to connectAsync
225+ // and disconnectAsync
226+ synchronized (m_connectLock)
227+ {
228+ // Disconnect from the publisher
229+ m_subscriber.disconnect();
230+
231+ // Create a new subscriber connector since we cancelled the old one
232+ m_connector = createSubscriberConnector(m_subscriptionInfo, m_outputStream);
233+ }
234+ }
235+ }).start();
236+ }
237+
238+ // Creates the text area to which we send our program output.
239+ private JTextArea createOutputTextArea()
240+ {
241+ JTextArea outputTextArea = new JTextArea();
242+ outputTextArea.setEditable(false);
243+ outputTextArea.setLineWrap(true);
244+ outputTextArea.setWrapStyleWord(true);
245+ return outputTextArea;
246+ }
247+
248+ // Creates the text field where the user enters the hostname.
249+ private JTextField createHostnameTextField()
250+ {
251+ JTextField hostnameTextField = new JTextField("localhost");
252+ hostnameTextField.addActionListener(m_connectListener);
253+ return hostnameTextField;
254+ }
255+
256+ // Creates the text field where the user enters the port number.
257+ private JTextField createPortTextField()
258+ {
259+ JTextField portTextField = new JTextField("6170");
260+ portTextField.addActionListener(m_connectListener);
261+ return portTextField;
262+ }
263+
264+ // Creates the button used to connect to the publisher.
265+ private JButton createConnectButton()
266+ {
267+ JButton connectButton = new JButton("Connect");
268+ connectButton.addActionListener(m_connectListener);
269+ return connectButton;
270+ }
271+
272+ // Creates the button used to disconnect from the publisher.
273+ private JButton createDisconnectButton()
274+ {
275+ JButton disconnectButton = new JButton("Disconnect");
276+ disconnectButton.addActionListener(m_disconnectListener);
277+ return disconnectButton;
278+ }
279+
280+ // Creates the box that contains the connect and disconnect buttons.
281+ private Box createButtonBox()
282+ {
283+ Box buttonBox = new Box(BoxLayout.X_AXIS);
284+ buttonBox.add(m_connectButton);
285+ buttonBox.add(m_disconnectButton);
286+ return buttonBox;
287+ }
288+
289+ // Creates the output stream that writes to the text area.
290+ private PrintStream createOutputStream()
291+ {
292+ return new PrintStream(new TextAreaOutputStream(m_outputTextArea));
293+ }
294+
295+ // SubscriptionInfo is a helper object which allows the user
296+ // to set up their subscription and resuse subscription settings.
297+ private SubscriptionInfo createSubscriptionInfo()
298+ {
299+ SubscriptionInfo info = new SubscriptionInfo();
300+
301+ // The following filter expression formats are also available:
302+ //
303+ // - Signal ID list -
304+ //info.setFilterExpression("7aaf0a8f-3a4f-4c43-ab43-ed9d1e64a255;" +
305+ // "93673c68-d59d-4926-b7e9-e7678f9f66b4;" +
306+ // "65ac9cf6-ae33-4ece-91b6-bb79343855d5;" +
307+ // "3647f729-d0ed-4f79-85ad-dae2149cd432;" +
308+ // "069c5e29-f78a-46f6-9dff-c92cb4f69371;" +
309+ // "25355a7b-2a9d-4ef2-99ba-4dd791461379");
310+ //
311+ // - Filter pattern -
312+ //info.setFilterExpression("FILTER ActiveMeasurements WHERE ID LIKE 'PPA:*'");
313+ //info.setFilterExpression("FILTER ActiveMeasurements WHERE Device = 'SHELBY' AND SignalType = 'FREQ'");
314+
315+ info.setFilterExpression("PPA:1;PPA:2;PPA:3;PPA:4;PPA:5;PPA:6;PPA:7;PPA:8;PPA:9;PPA:10;PPA:11;PPA:12;PPA:13;PPA:14");
316+
317+ // To set up a remotely synchronized subscription, set this flag
318+ // to true and add the framesPerSecond parameter to the
319+ // ExtraConnectionStringParameters. Additionally, the following
320+ // example demonstrates the use of some other useful parameters
321+ // when setting up remotely synchronized subscriptions.
322+ //
323+ //info.setRemotelySynchronized(true);
324+ //info.setExtraConnectionStringParameters("framesPerSecond=30;timeResolution=10000;downsamplingMethod=Closest");
325+
326+ info.setRemotelySynchronized(false);
327+ info.setThrottled(false);
328+
329+ info.setUdpDataChannel(true);
330+ info.setDataChannelLocalPort(9600);
331+
332+ info.setTimeIncluded(true);
333+ info.setLagTime(3.0);
334+ info.setLeadTime(1.0);
335+ info.setLocalClockAsRealTime(false);
336+ info.setMillisecondResolution(true);
337+
338+ return info;
339+ }
340+
341+ // SubscriberConnector is another helper object which allows the
342+ // user to modify settings for auto-reconnects and retry cycles.
343+ private SubscriberConnector createSubscriberConnector(SubscriptionInfo info, PrintStream outputStream)
344+ {
345+ SubscriberConnector connector = new SubscriberConnector();
346+ SubscriberConnectorListener listener = new SampleSubscriberConnectorListener(info, outputStream);
347+
348+ connector.setMaxRetries(-1);
349+ connector.setRetryInterval(5000);
350+ connector.setAutoReconnect(true);
351+ connector.addSubscriberConnectorListener(listener);
352+
353+ return connector;
354+ }
355+
356+ // Creates the data subscriber.
357+ private DataSubscriber createSubscriber()
358+ {
359+ DataSubscriber subscriber = new DataSubscriber();
360+ subscriber.addSubscriberListener(new SampleSubscriberListener(m_outputStream, m_outputStream));
361+ return subscriber;
362+ }
363+
364+ private static final long serialVersionUID = -787591661184215315L;
365+
366+ // OutputStream that, when wrapped by a
367+ // PrintStream, allows for output to a JTextArea.
368+ private class TextAreaOutputStream extends OutputStream
369+ {
370+ private ByteBuffer m_buffer;
371+ private JTextArea m_outputArea;
372+
373+ public TextAreaOutputStream(JTextArea outputTextArea)
374+ {
375+ if (outputTextArea == null)
376+ throw new IllegalArgumentException("outputTextArea must not be null");
377+
378+ m_buffer = ByteBuffer.allocate(2000);
379+ m_outputArea = outputTextArea;
380+ }
381+
382+ @Override
383+ public void flush() throws IOException
384+ {
385+ m_buffer.flip();
386+ append(Charset.defaultCharset().decode(m_buffer).toString());
387+ m_buffer = m_buffer.compact();
388+ }
389+
390+ @Override
391+ public void write(byte[] b) throws IOException
392+ {
393+ write(b, 0, b.length);
394+ }
395+
396+ @Override
397+ public void write(byte[] b, int off, int len) throws IOException
398+ {
399+ int rem = m_buffer.remaining();
400+
401+ if (len <= rem)
402+ {
403+ m_buffer.put(b, off, len);
404+
405+ if (m_buffer.position() >= DumpThreshold)
406+ flush();
407+ }
408+ else
409+ {
410+ m_buffer.put(b, off, rem);
411+ flush();
412+
413+ for (int i = rem; i < len; i += m_buffer.capacity())
414+ {
415+ rem = Math.min(m_buffer.remaining(), len - i);
416+ m_buffer.put(b, off + i, rem);
417+ flush();
418+ }
419+ }
420+ }
421+
422+ @Override
423+ public void write(int b) throws IOException
424+ {
425+ m_buffer.put((byte)b);
426+
427+ if (m_buffer.position() >= DumpThreshold)
428+ flush();
429+ }
430+
431+ private void append(final String text)
432+ {
433+ SwingUtilities.invokeLater(new Runnable()
434+ {
435+ @Override
436+ public void run()
437+ {
438+ StringBuilder textBuilder = new StringBuilder(m_outputArea.getText());
439+
440+ textBuilder.append(text);
441+
442+ while (textBuilder.length() > CharacterLimit)
443+ textBuilder.delete(0, textBuilder.indexOf(System.lineSeparator()) + 1);
444+
445+ m_outputArea.setText(textBuilder.toString());
446+ }
447+ });
448+ }
449+
450+ private static final int DumpThreshold = 50;
451+ private static final int CharacterLimit = 8192;
452+ }
453+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t