View Javadoc
1   // NAME
2   //      $RCSfile: DialogChannelStatusBean.java,v $
3   // DESCRIPTION
4   //      [given below in javadoc format]
5   // DELTA
6   //      $Revision: 1.18 $
7   // CREATED
8   //      $Date: 2006/02/02 15:49:39 $
9   // COPYRIGHT
10  //      Westhawk Ltd
11  // TO DO
12  //
13  
14  /*
15   * Copyright (C) 1998 - 2006 by Westhawk Ltd
16   *
17   * Permission to use, copy, modify, and distribute this software
18   * for any purpose and without fee is hereby granted, provided
19   * that the above copyright notices appear in all copies and that
20   * both the copyright notice and this permission notice appear in
21   * supporting documentation.
22   * This software is provided "as is" without express or implied
23   * warranty.
24   * author <a href="mailto:snmp@westhawk.co.uk">Tim Panton</a>
25   */
26  
27  package uk.co.westhawk.snmp.beans;
28  
29  /*-
30   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
31   * SNMP Java Client
32   * ჻჻჻჻჻჻
33   * Copyright 2023 MetricsHub, Westhawk
34   * ჻჻჻჻჻჻
35   * This program is free software: you can redistribute it and/or modify
36   * it under the terms of the GNU Lesser General Public License as
37   * published by the Free Software Foundation, either version 3 of the
38   * License, or (at your option) any later version.
39   *
40   * This program is distributed in the hope that it will be useful,
41   * but WITHOUT ANY WARRANTY; without even the implied warranty of
42   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
43   * GNU General Lesser Public License for more details.
44   *
45   * You should have received a copy of the GNU General Lesser Public
46   * License along with this program.  If not, see
47   * <http://www.gnu.org/licenses/lgpl-3.0.html>.
48   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
49   */
50  
51  import uk.co.westhawk.snmp.stack.*;
52  import uk.co.westhawk.snmp.pdu.*;
53  
54  import javax.swing.tree.*;
55  import java.awt.*;
56  import java.util.*;
57  import java.text.*;
58  import java.lang.*;
59  import java.io.*;
60  import java.beans.*;
61  
62  /**
63   * <p>
64   * This bean is written for a Dialogic card.
65   *
66   * The Dialogic MIBs come with their 
67   * <a
68   * href="http://support.dialogic.com/Download/boardwatch/index.htm">BoardWatch
69   * package</a>. You will have to fill in a form before downloading it.
70   *
71   * <p>
72   * This bean collects information about the voice channel status of the
73   * Dialogic card. It will only collect those channels that are open.
74   * </p>
75   *
76   * <p>
77   * You can get the data via the getChannelIndexes() and 
78   * getChannelStatus(Integer index) methods. This way you can visualise
79   * the data yourself. 
80   * </p>
81   *
82   * <p>
83   * You can also use the Swing JTree to visualise the channels.
84   * This bean implements the Swing TreeNode interface. 
85   * The user has to set the setDefaultTreeModel, so this class can update all
86   * the nodes that are added, removed of changed.
87   * If this class is <em>not</em> the root of the JTree, you have to set
88   * the (TreeNode) parent of this class.
89   * </p>
90   *
91   * <p>
92   * The properties in the parent classes should be set, before calling
93   * the action() method. Via a TreeModelEvent the application/applet
94   * will be notified. 
95   * </p>
96   *
97   * <p>
98   * We only have one (1) Dialogics card, so I don't know how and if it
99   * works with more than 1 card. Please let us know if it doesn't work.
100  * </p>
101  *
102  * @see SNMPBean#setHost
103  * @see SNMPBean#setPort
104  * @see SNMPBean#setCommunityName
105  * @see SNMPRunBean#setUpdateInterval
106  * @see SNMPBean#addPropertyChangeListener
107  * @see SNMPBean#action
108  * @see GetNextPdu_vec
109  * 
110  * @author <a href="mailto:snmp@westhawk.co.uk">Birgit Arkesteijn</a>
111  * @version $Revision: 1.18 $ $Date: 2006/02/02 15:49:39 $
112  *
113  */
114 public class DialogChannelStatusBean extends SNMPRunBean
115         implements Observer, TreeNode {
116     private static final String version_id = "@(#)$Id: DialogChannelStatusBean.java,v 1.18 2006/02/02 15:49:39 birgit Exp $ Copyright Westhawk Ltd";
117 
118     /**
119      * A unique value for each R4 device contained by the
120      * host. The value for each R4 device must remain
121      * constant at least from one re-initialization of the
122      * agent to the next re-initialization.
123      *
124      * See the dlgr4dev.mib.
125      */
126     public final static String dlgR4DeviceIndex = "1.3.6.1.4.1.3028.2.1.1.2.1.1.1";
127 
128     /**
129      * Release 4 Device Name. This is the name the application will
130      * use when opening the device (e.g. dxxxB1C1, dtiB1T1, msiB1C1)
131      * See the dlgr4dev.mib.
132      */
133     public final static String dlgR4DeviceName = "1.3.6.1.4.1.3028.2.1.1.2.1.1.2";
134 
135     /**
136      * An indication of the type of the device.
137      * <ol>
138      * <li>
139      * other - some other type of device unknown to the agent.</li>
140      * <li>
141      * voice - A voice channel device. An entry exits in the
142      * dlgR4VoiceTable for this device.</li>
143      * <li>
144      * dti - A DTI timeslot device. An entry exits in the
145      * dlgR4DTITable for this device.</li>
146      * <li>
147      * isdn - An ISDN B-Channel device. An entry exits in the
148      * dlgR4ISDNTable for this device.</li>
149      * <li>
150      * msi - An MSI station set device. An entry exits in the
151      * dlgR4MSITable for this device.</li>
152      * </ol>
153      * 
154      * See the dlgr4dev.mib.
155      */
156     public final static String dlgR4DeviceType = "1.3.6.1.4.1.3028.2.1.1.2.1.1.3";
157 
158     /**
159      * An indication of how many instances of this device is currently
160      * opened.
161      * See the dlgr4dev.mib.
162      */
163     public final static String dlgR4DeviceOpenCount = "1.3.6.1.4.1.3028.2.1.1.2.1.1.5";
164 
165     /**
166      * Indicates current activity status on the (voice) channel.
167      * See the dlgr4dev.mib.
168      */
169     public final static String dlgR4VoiceChannelStatus = "1.3.6.1.4.1.3028.2.1.1.2.2.1.2";
170 
171     private final static int NR_OID = 5;
172 
173     // dlgR4DeviceType values
174     public final static int unknown = 1;
175     public final static int voice = 2;
176     public final static int dti = 3;
177     public final static int isdn = 4;
178     public final static int msi = 5;
179 
180     // dlgR4VoiceChannelStatus values
181     public final static int idle = 1;
182     public final static int playing = 2;
183     public final static int recording = 3;
184     public final static int gettingDigits = 5;
185     public final static int blocked = 16;
186 
187     public final static int dialing = 4;
188     public final static int playTone = 6;
189     public final static int sendingFax = 8;
190     public final static int receivingFax = 9;
191     public final static int betweenFAXPages = 10;
192     public final static int hookState = 11;
193     public final static int winking = 12;
194     public final static int callProgess = 13;
195     public final static int gettingR2MF = 14;
196 
197     public final static String vch_status[] = {
198             "",
199             "Channel not active",
200             "Playing Audio Data",
201             "Recording Audio Data",
202             "Dialing Digits",
203             "Collecting DTMF digits",
204             "Playing a tone",
205             "",
206             "Sending a FAX (VFX boards)",
207             "Receiving a FAX (VFX boards)",
208             "Between FAX pages (VFX boards)",
209             "Changing hook status to onhook or offhook",
210             "Performing a wink",
211             "Performing Call progress analysis",
212             "Retrieving R2MF digits",
213             "",
214             "Blocked"
215     };
216 
217     private GetNextPdu_vec pdu;
218     private Hashtable channelIndexStatusHash;
219     private Hashtable channelHash;
220 
221     private TreeNode parent;
222     private DefaultTreeModel treeModel;
223 
224     private boolean isGetNextInFlight;
225     private Date lastUpdateDate = null;
226 
227     private int deviceType = 0;
228     private String deviceName = "";
229     private int openCount = 0;
230     private int channelStatus = 0;
231 
232     /**
233      * The default constructor.
234      */
235     public DialogChannelStatusBean() {
236         channelIndexStatusHash = new Hashtable();
237         channelHash = new Hashtable();
238     }
239 
240     /**
241      * The constructor that will set the host and the port no.
242      *
243      * @param h the hostname
244      * @param p the port no
245      * @see SNMPBean#setHost
246      * @see SNMPBean#setPort
247      */
248     public DialogChannelStatusBean(String h, int p) {
249         this(h, p, null);
250     }
251 
252     /**
253      * The constructor that will set the host, the port no and the local
254      * bind address.
255      *
256      * @param h the hostname
257      * @param p the port no
258      * @param b the local bind address
259      * @see SNMPBean#setHost
260      * @see SNMPBean#setPort
261      * @see SNMPBean#setBindAddress
262      *
263      * @since 4_14
264      */
265     public DialogChannelStatusBean(String h, int p, String b) {
266         this();
267         setHost(h);
268         setPort(p);
269         setBindAddress(b);
270     }
271 
272     /**
273      * Returns the date of the moment when this bean was last updated.
274      * This might be null when the first time the update was not finished.
275      *
276      * @return the last update date
277      */
278     public Date getLastUpdateDate() {
279         return lastUpdateDate;
280     }
281 
282     /**
283      * Returns the indexes (as Integers) of the voice channels that are
284      * open. Only the open voice channels of the card are saved.
285      * 
286      * Use getChannelStatus() or getChannelStatusString() to get the status
287      * of the channel.
288      *
289      * @see #getChannelStatus
290      * @see #getChannelStatusString
291      */
292     public Enumeration getChannelIndexes() {
293         return channelIndexStatusHash.keys();
294     }
295 
296     /**
297      * Returns the number of voice channels in the table.
298      */
299     public synchronized int getChannelCount() {
300         return channelIndexStatusHash.size();
301     }
302 
303     /**
304      * Returns the name of the channel.
305      *
306      * @param index The index of the channel
307      * @return The name
308      *
309      */
310     public String getChannelName(Integer index) {
311         String name = "";
312         Object obj = channelHash.get(index);
313         if (obj != null) {
314             ChannelStatus chSt = (ChannelStatus) obj;
315             name = chSt.getName();
316         }
317         return name;
318     }
319 
320     /**
321      * Returns the status of the channel as an int.
322      *
323      * @param index The index of the channel
324      * @return The status
325      *
326      * @see #getChannelIndexes
327      */
328     public int getChannelStatus(Integer index) {
329         int status = 0;
330         Object obj = channelIndexStatusHash.get(index);
331         if (obj != null) {
332             status = ((Integer) obj).intValue();
333         }
334         return status;
335     }
336 
337     /**
338      * Returns the String representation of the status of the channel.
339      *
340      * @param index The index of the channel
341      * @return The status
342      *
343      * @see #getChannelIndexes
344      */
345     public String getChannelStatusString(Integer index) {
346         int status = getChannelStatus(index);
347         String str = vch_status[status];
348         return str;
349     }
350 
351     /**
352      * Returns the children of the reciever as an Enumeration.
353      */
354     public Enumeration children() {
355         return channelHash.elements();
356     }
357 
358     /**
359      * Returns the number of children <code>TreeNode</code>s the receiver
360      * contains.
361      */
362     public int getChildCount() {
363         int sz = channelHash.size();
364         return sz;
365     }
366 
367     /**
368      * Returns the child <code>TreeNode</code> at index
369      * <code>childIndex</code>.
370      */
371     public TreeNode getChildAt(int childIndex) {
372         TreeNode node = null;
373         if (childIndex < channelHash.size()) {
374             Enumeration e = channelHash.elements();
375             for (int i = 0; i <= childIndex; i++) {
376                 node = (TreeNode) e.nextElement();
377             }
378         }
379         return node;
380     }
381 
382     /**
383      * Returns the index of <code>node</code> in the receivers children.
384      * If the receiver does not contain <code>node</code>, -1 will be
385      * returned.
386      */
387     public int getIndex(TreeNode node) {
388         int ret = -1;
389         if (channelHash.contains(node)) {
390             boolean found = false;
391             Enumeration e = channelHash.elements();
392             while (e.hasMoreElements() && !found) {
393                 TreeNode n = (TreeNode) e.nextElement();
394                 found = (n == node);
395                 ret++;
396             }
397         }
398         return ret;
399     }
400 
401     /**
402      * Returns the parent <code>TreeNode</code> of the receiver.
403      */
404     public TreeNode getParent() {
405         return parent;
406     }
407 
408     /**
409      * Returns true if the receiver allows children.
410      */
411     public boolean getAllowsChildren() {
412         return true;
413     }
414 
415     /**
416      * Returns true if the receiver is a leaf.
417      */
418     public boolean isLeaf() {
419         return false;
420     }
421 
422     /**
423      * This method starts the action of the bean. It will initialises
424      * all variables before starting.
425      */
426     public void action() {
427         if (isHostPortReachable()) {
428             lastUpdateDate = new Date();
429             isGetNextInFlight = false;
430             setRunning(true);
431         }
432     }
433 
434     /**
435      * Implements the running of the bean.
436      *
437      * It will send the Pdu, if the previous one is not still in flight.
438      * 
439      * @see SNMPRunBean#isRunning()
440      */
441     public void run() {
442         while (context != null && isRunning()) {
443             if (isGetNextInFlight == false) {
444                 // start the GetNext loop again
445                 isGetNextInFlight = true;
446 
447                 pdu = new GetNextPdu_vec(context, NR_OID);
448                 pdu.addObserver(this);
449 
450                 pdu.addOid(dlgR4DeviceIndex);
451                 pdu.addOid(dlgR4DeviceName);
452                 pdu.addOid(dlgR4DeviceType);
453                 pdu.addOid(dlgR4DeviceOpenCount);
454                 pdu.addOid(dlgR4VoiceChannelStatus);
455                 try {
456                     pdu.send();
457                 } catch (PduException exc) {
458                     System.out.println("PduException " + exc.getMessage());
459                 } catch (IOException exc) {
460                     System.out.println("IOException " + exc.getMessage());
461                 }
462             }
463 
464             try {
465                 Thread.sleep(interval);
466             } catch (InterruptedException ix) {
467                 ;
468             }
469         }
470     }
471 
472     /**
473      * This method is called when the Pdu response is received. When all
474      * answers are received it will fire the property change event.
475      *
476      */
477     public void update(Observable obs, Object ov) {
478         boolean hasEnded = false;
479         int index;
480         varbind[] var;
481 
482         pdu = (GetNextPdu_vec) obs;
483 
484         if (pdu.isTimedOut() == false) {
485             if (pdu.getErrorStatus() == AsnObject.SNMP_ERR_NOERROR) {
486                 var = (varbind[]) ov;
487                 if (var[0].getOid().toString().startsWith(dlgR4DeviceIndex)) {
488                     index = ((AsnInteger) var[0].getValue()).getValue();
489                     deviceName = ((AsnOctets) var[1].getValue()).getValue();
490                     deviceType = ((AsnInteger) var[2].getValue()).getValue();
491                     openCount = ((AsnInteger) var[3].getValue()).getValue();
492                     channelStatus = ((AsnInteger) var[4].getValue()).getValue();
493 
494                     if (deviceType == voice) {
495                         Integer indexInt = new Integer(index);
496                         if (openCount == 0) {
497                             channelIndexStatusHash.remove(indexInt);
498                             channelHash.remove(indexInt);
499                         } else {
500                             channelIndexStatusHash.put(indexInt,
501                                     new Integer(channelStatus));
502 
503                             ChannelStatus cStatus = (ChannelStatus) channelHash.get(indexInt);
504 
505                             if (cStatus == null) {
506                                 cStatus = new ChannelStatus(index, channelStatus,
507                                         deviceName, this);
508                                 channelHash.put(indexInt, cStatus);
509                             } else {
510                                 cStatus.setStatus(channelStatus);
511                             }
512                         }
513                     }
514 
515                     // ask for the next channel
516                     pdu = new GetNextPdu_vec(context, NR_OID);
517                     pdu.addObserver(this);
518 
519                     pdu.addOid(var[0].getOid().toString());
520                     pdu.addOid(var[1].getOid().toString());
521                     pdu.addOid(var[2].getOid().toString());
522                     pdu.addOid(var[3].getOid().toString());
523                     pdu.addOid(var[4].getOid().toString());
524                     try {
525                         pdu.send();
526                     } catch (PduException exc) {
527                         System.out.println("PduException " + exc.getMessage());
528                     } catch (IOException exc) {
529                         System.out.println("IOException " + exc.getMessage());
530                     }
531                 } else {
532                     hasEnded = true;
533                 }
534             } else {
535                 hasEnded = true;
536             }
537         } else {
538             channelIndexStatusHash.clear();
539             channelHash.clear();
540             hasEnded = true;
541         }
542 
543         if (hasEnded) {
544             // the GetNext loop has ended
545             lastUpdateDate = new Date();
546             javax.swing.SwingUtilities.invokeLater(new TreeUpdate());
547             isGetNextInFlight = false;
548         }
549     }
550 
551     /**
552      * Sets the parent for this TreeNode. If the parent is not set, this
553      * class should be the root of the TreeModel.
554      */
555     public void setParent(TreeNode p) {
556         parent = p;
557     }
558 
559     /**
560      * Sets the DefaultTreeModel for this TreeNode. The tree model is used
561      * for notifying when any of the nodes were added, removed or changed.
562      */
563     public void setDefaultTreeModel(DefaultTreeModel model) {
564         treeModel = model;
565     }
566 
567     /**
568      * Fire the property event.
569      *
570      * @see
571      *      DefaultTreeModel#nodeStructureChanged
572      */
573     protected void fireTreeModelChanged() {
574         if (treeModel != null) {
575             treeModel.nodeStructureChanged(this);
576         }
577     }
578 
579     class ChannelStatus extends Object implements TreeNode {
580         private TreeNode parent;
581         private int index, status;
582         private String name;
583 
584         public ChannelStatus(int ind, int st, String nm, TreeNode par) {
585             index = ind;
586             status = st;
587             name = nm;
588             parent = par;
589         }
590 
591         public int getIndex() {
592             return index;
593         }
594 
595         public int getStatus() {
596             return status;
597         }
598 
599         public void setStatus(int st) {
600             status = st;
601         }
602 
603         public String getName() {
604             return name;
605         }
606 
607         public String toString() {
608             return "" + index + " " + name + " " + vch_status[status];
609         }
610 
611         /**
612          * Returns the children of the reciever as an Enumeration.
613          */
614         public Enumeration children() {
615             return null;
616         }
617 
618         /**
619          * Returns the number of children <code>TreeNode</code>s the receiver
620          * contains.
621          */
622         public int getChildCount() {
623             return 0;
624         }
625 
626         /**
627          * Returns the child <code>TreeNode</code> at index
628          * <code>childIndex</code>.
629          */
630         public TreeNode getChildAt(int childIndex) {
631             return null;
632         }
633 
634         /**
635          * Returns the index of <code>node</code> in the receivers children.
636          * If the receiver does not contain <code>node</code>, -1 will be
637          * returned.
638          */
639         public int getIndex(TreeNode node) {
640             return -1;
641         }
642 
643         /**
644          * Returns the parent <code>TreeNode</code> of the receiver.
645          */
646         public TreeNode getParent() {
647             return parent;
648         }
649 
650         /**
651          * Returns true if the receiver allows children.
652          */
653         public boolean getAllowsChildren() {
654             return true;
655         }
656 
657         /**
658          * Returns true if the receiver is a leaf.
659          */
660         public boolean isLeaf() {
661             return true;
662         }
663 
664     } // end class ChannelStatus
665 
666     class TreeUpdate implements Runnable {
667         public void run() {
668             fireTreeModelChanged();
669             firePropertyChange("modems", null, null);
670         }
671     }
672 
673 }