Bluetooth connection manager in Mobile Java J2ME


2009-03-17 Digg! icurtain Delcious icurtain Technorati icurtain


This Bluetooth Java connection manager class and its data package class have quite a few issues - main one being that the thread for checking the incoming data stream should be reading each byte of data and queuing it rather than trying to receive discrete packages of data and queueing them - will be fixed and updated at some stage.

  1. /* 
  2. * copyright - mike lang - icurtain.co.uk 
  3. * blutooth connection manager - 0.1 
  4. * has some rather dodgy flaws - multi-threading is currently incorrectly implemented 
  5. *  
  6. */ 
  7.  
  8. package utilities; 
  9.  
  10. // Bluetooth Libraries 
  11. import javax.bluetooth.*; 
  12. import javax.microedition.io.*; 
  13. import java.io.*; 
  14. import java.util.Vector; 
  15. /** 
  16. * @author mike lang 
  17. */ 
  18. public class ConnectionManager implements Runnable { 
  19.  
  20.        //bluetooth vars 
  21.       public LocalDevice local; 
  22.       public StreamConnectionNotifier notifier; 
  23.       public DiscoveryAgent agent; 
  24.  
  25.  
  26.       private boolean active = false; 
  27.       private boolean server = false; 
  28.       private int packetSize = 15; 
  29.       boolean tx = false; 
  30.  
  31.  
  32.       //new stuff 
  33.       private String btSerial = "86b4d249fb8844d6a756ec265dd1f6a3"; 
  34.       //output stream to write to 
  35.       private StreamConnection streamConnection; 
  36.       private ServiceRecord serviceRecord; 
  37.        
  38.       private OutputStream outputStream; 
  39.       //input stream fromw hich to read 
  40.       private InputStream inputStream; 
  41.        
  42.       private Vector sendQueue; 
  43.       private Vector receiveQueue; 
  44.        
  45.       private boolean threadQuit; 
  46.  
  47.       private String dataStart = "<"; 
  48.       private String dataStop = ">"; 
  49.       private String dataBreak = "@"; 
  50.        
  51.       private String incompleteData; 
  52.       private int threadSleep = 100; 
  53.  
  54.        
  55.       public void run(){ 
  56.             while(!threadQuit){ 
  57.                    
  58.                   if(this.isActive()){ 
  59.                         this.communicate(); 
  60.                   } 
  61.                 // System.out.println("COMMS THREADLOOP"); 
  62.                   try { 
  63.                         //Sleep for 100 milliseconds, or 1/10 of a // 
  64.                         Thread.sleep(threadSleep); 
  65.                         //second.    The sleep method chucks up an   // 
  66.                   }    //exception.                                              // 
  67.                   catch (Exception ee) { 
  68.                         System.out.println(ee); 
  69.                   } 
  70.             } 
  71.       } 
  72.  
  73.  
  74.        
  75.  
  76.       public synchronized void   addSendQueue(BTPackage btp){ 
  77.             //we are typing the list info as Strings 
  78.              
  79.                   if(sendQueue==null){ 
  80.                         sendQueue = new Vector(); 
  81.                         } 
  82.                   //now its in the queue calc the checksum 
  83.                   btp.calcCheckSum(); 
  84.                   sendQueue.addElement(new BTPackage(btp)); 
  85.              
  86.       } 
  87.  
  88.       private BTPackage consumeSendQueue(){ 
  89.             //we can either type to string or just store objects 
  90.             if(sendQueue != null && !sendQueue.isEmpty()){ 
  91.                   BTPackage btp = (BTPackage)sendQueue.lastElement(); 
  92.                   sendQueue.removeElement(sendQueue.lastElement()); 
  93.                   return btp; 
  94.             } 
  95.             return null; 
  96.       } 
  97.        
  98.       private void addRecieveQueue(BTPackage btp){ 
  99.             if(receiveQueue==null){ 
  100.                   receiveQueue = new Vector(); 
  101.             } 
  102.             receiveQueue.addElement(new BTPackage(btp)); 
  103.       } 
  104.        
  105.        
  106.       public synchronized boolean checkReceiveQueue(){ 
  107.             if(receiveQueue != null && !receiveQueue.isEmpty()){ 
  108.                   return true; 
  109.             }return false; 
  110.       } 
  111.        
  112.       public synchronized BTPackage getReceiveQueue(){ 
  113.                   //we can either type to string or just store objects 
  114.                   if(this.checkReceiveQueue()){ 
  115.                         BTPackage btp = (BTPackage)receiveQueue.lastElement(); 
  116.                         receiveQueue.removeElement(receiveQueue.lastElement()); 
  117.                         return btp; 
  118.                   }return null; 
  119.       } 
  120.        
  121.       //code here 
  122.  
  123.       public void setBtSerial(String btSerial){ 
  124.             this.btSerial = btSerial; 
  125.       } 
  126.  
  127.       public String getBtSerial(){ 
  128.             return this.btSerial; 
  129.       } 
  130.  
  131.       private void setActive(boolean active){ 
  132.             this.active = active; 
  133.       } 
  134.        
  135.       public boolean isActive(){ 
  136.             return this.active; 
  137.       } 
  138.        
  139.       public boolean isServer() { 
  140.             return server; 
  141.       } 
  142.  
  143.       private void setServer(boolean server) { 
  144.             this.server = server; 
  145.       } 
  146.  
  147.       public void startServer(){ 
  148.             // server code 
  149.             if(!this.isActive()){ 
  150.                    
  151.              
  152.             try { 
  153.                    
  154.                   local = LocalDevice.getLocalDevice(); 
  155.                   if (!local.setDiscoverable(DiscoveryAgent.GIAC)) { 
  156.                         System.out.println("Failed to change to the discoverable mode"); 
  157.                         return; 
  158.                   } 
  159.                 
  160.                   notifier = (StreamConnectionNotifier) Connector.open("btspp://localhost:" + this.getBtSerial()); 
  161.                 // System.out.println("btspp://localhost:" + this.getBtSerial()); 
  162.                    
  163.                   streamConnection = (StreamConnection) notifier.acceptAndOpen(); 
  164.                    
  165.                   inputStream = streamConnection.openInputStream(); 
  166.                   //may have to remove this line below; 
  167.                   outputStream =streamConnection.openOutputStream(); 
  168.                   //ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  169.                   this.setActive(true); 
  170.                   this.setServer(true); 
  171.                    
  172.                    
  173.                   ByteArrayOutputStream out = new ByteArrayOutputStream(); 
  174.                    
  175.  
  176.             } catch (BluetoothStateException e){ 
  177.                   System.out.println("BluetoothStateException:" + e.getMessage()); 
  178.             } catch (IOException e){ 
  179.                   System.out.println("IOException:" + e.getMessage()); 
  180.             } 
  181.             } 
  182.       } 
  183.  
  184.        public void startClient(){ 
  185.             try { 
  186.                    
  187.                   agent = LocalDevice.getLocalDevice().getDiscoveryAgent(); 
  188.                    
  189.                  
  190.                   String connectionString = agent.selectService( 
  191.                               new UUID(btSerial, false), 
  192.                               ServiceRecord.NOAUTHENTICATE_NOENCRYPT, false); 
  193.                    
  194.                   if (connectionString != null) { 
  195.                         //    System.out.println("trying to send bluetooth client data"); 
  196.                         try { 
  197.                                
  198.                               streamConnection = (StreamConnection) Connector.open(connectionString); 
  199.                               outputStream = streamConnection.openOutputStream(); 
  200.                               inputStream = streamConnection.openInputStream(); 
  201.  
  202.                               System.out.println("initiating a connection"); 
  203.                               this.setActive(true); 
  204.                               this.setServer(false); 
  205.                         } catch (IOException e) { 
  206.                               System.out.println("IOException:" + e.getMessage()); 
  207.                         } 
  208.                   } else { 
  209.                         System.out.println("Unable To Locate Service"); 
  210.                   } 
  211.  
  212.             } catch (BluetoothStateException e){ 
  213.                   System.out.println("BluetoothStateException:" + e.getMessage()); 
  214.             } 
  215.              
  216.              
  217.       } 
  218.  
  219.         
  220.       private void communicate(){ 
  221.           // synchronized( this ){ 
  222.                   System.out.println("network thread"); 
  223.           
  224.                      if(this.isServer()) { 
  225.                                        this.sendData(); 
  226.                                        this.receiveData(); 
  227.                         }else{ 
  228.                                           this.receiveData(); 
  229.                                           this.sendData(); 
  230.                         } 
  231.             // } 
  232.       }  
  233.  
  234.     
  235.              
  236.        
  237.       private void sendData(){ 
  238.             //OutputStream outputStream = streamConnection.openOutputStream(); 
  239.             String data = ""; 
  240.             //we should be consuming the send queue here 
  241.             if((this.sendQueue != null)&&(!this.sendQueue.isEmpty())){ 
  242.                   data = this.encodeBTPackage(this.consumeSendQueue()); 
  243.                   System.out.println("SENDING:" + data); 
  244.              
  245.                   if (this.streamConnection != null) { 
  246.                   //   System.out.println("trying to send bluetooth client data"); 
  247.                         try { 
  248.                               //data = dataStart+data+dataStop; 
  249.                               outputStream.write(data.getBytes()); 
  250.                               } catch (IOException e) { 
  251.                               System.out.println("IOException:" + e.getMessage()); 
  252.                         } 
  253.                   }  
  254.                   //set to receive 
  255.             } 
  256.              
  257.              
  258.            
  259.            
  260.       } 
  261.       private void receiveData(){ 
  262.             byte[] dataBuffer; 
  263.             String tempData = ""; 
  264.             boolean endOfPackage = false; 
  265.              
  266.             int input; 
  267.             try { 
  268.                   while ((input = inputStream.read()) >= 0){ 
  269.                         //System.out.println("XX "+(char) input); 
  270.                         tempData += (char) input; 
  271.                          
  272.                         //THIS SECTION MUST RELINQUISH READING OR IT WILL CARRY ON READING THE WHOLE OUTPUTSTREAM!!!! 
  273.  
  274.                         if(String.valueOf((char)input).equals(dataStop)){ 
  275.                             // this.addRecieveQueue(tempData); 
  276.                             // System.out.println("ADDED: "+ tempData); 
  277.                             // return; 
  278.                               break; 
  279.                         } 
  280.                          
  281.                   }    
  282.                   System.out.println("PROCESSED: "+ tempData); 
  283.                   this.addRecieveQueue(this.unencodeBTPackage(tempData)); 
  284.              } catch (IOException ex) { 
  285.                   ex.printStackTrace(); 
  286.             } 
  287.             } 
  288.        
  289.             public void terminate(){ 
  290.                   try{ 
  291.                         this.streamConnection.close(); 
  292.                   }catch(IOException e){ 
  293.                         System.out.println(e.toString()); 
  294.                   } 
  295.                   this.setActive(false); 
  296.             } 
  297.              
  298.             public boolean isThreadQuit() { 
  299.             return threadQuit; 
  300.       } 
  301.  
  302.       public void setThreadQuit(boolean threadQuit) { 
  303.             this.threadQuit = threadQuit; 
  304.       } 
  305.       private String encodeBTPackage(BTPackage data){ 
  306.             String string = ""; 
  307.             data.calcCheckSum(); 
  308.             string =    this.dataStart +  
  309.                             data.getNameSpace() +  
  310.                             this.dataBreak +  
  311.                             data.getData() +  
  312.                             this.dataBreak + 
  313.                             String.valueOf(data.getCheckSum()) + 
  314.                             this.dataBreak + 
  315.                             String.valueOf(data.getTime()) +  
  316.                             this.dataStop; 
  317.             return string; 
  318.       } 
  319.        
  320.       private BTPackage unencodeBTPackage(String data){ 
  321.             //we are currently using 4 fields so the string has to be split into an array 
  322.             Vector list = new Vector(); 
  323.             String temp = ""; 
  324.           // temp = data.substring(packetSize, packetSize) 
  325.             //split string into array 
  326.             int j = 0; 
  327.             //this loop checks for the data break and if it finds it creates 
  328.             for(int i = 1;i<(data.length()-1);i++){ 
  329.                   if(!data.substring(i,(i+1)).equals(this.dataBreak)){ 
  330.                   temp += data.substring(i,(i+1)); 
  331.                   }else{ 
  332.                         list.addElement(new String(temp)); 
  333.                         temp = ""; 
  334.                         j++; 
  335.                         //System.out.println(data.substring(i,(i+1))); 
  336.                   } 
  337.             } 
  338.             //catch the last list element here rather than doing a double compare in the if  
  339.             list.addElement(new String(temp)); 
  340.              
  341.             /*for(int i = 0; i < list.size();i++){ 
  342.                   System.out.println((String)list.elementAt(i)); 
  343.             }*/ 
  344.              
  345.             BTPackage btp = new BTPackage(); 
  346.             btp.setNameSpace((String)list.elementAt(0)); 
  347.             btp.setData((String)list.elementAt(1)); 
  348.             //the quickest way seems to be to convert from object cast as String to long 
  349.             //btp.setTime(Long.parseLong((String) list.elementAt(2))); 
  350.             //btp.setCheckSum(Long.parseLong((String)list.elementAt(3))); 
  351.              
  352.             return btp; 
  353.            
  354.       } 
  355.  
  356.  
  357.  
  358. /* 
  359. * copyright - mike lang - icurtain.co.uk 
  360. * blutooth connection manager - 0.1 
  361. * data package  
  362. */ 
  363.  
  364. package utilities; 
  365.  
  366. /** 
  367. * @author mike lang 
  368. */ 
  369. public class BTPackage { 
  370.  
  371.       //live variable says if the data package is live or  
  372.        
  373.       private boolean live = true; 
  374.       private String nameSpace = ""; 
  375.       private String data = ""; 
  376.       private long checkSum; 
  377.       private long time; 
  378.        
  379.      
  380.       public BTPackage(){ 
  381.             this.time = System.currentTimeMillis(); 
  382.       } 
  383.       //alternate constructor 
  384.       public BTPackage(BTPackage btp){ 
  385.             this.setNameSpace(btp.getNameSpace()); 
  386.             this.setData(btp.getData()); 
  387.             this.setTime(btp.getTime()); 
  388.             this.setCheckSum(btp.getCheckSum()); 
  389.       } 
  390.  
  391.    public String getData() { 
  392.             return data; 
  393.       } 
  394.  
  395.       public void setData(String data) { 
  396.             this.data = data; 
  397.       } 
  398.  
  399.       public boolean isLive() { 
  400.             return live; 
  401.       } 
  402.  
  403.       public void setLive(boolean live) { 
  404.             this.live = live; 
  405.       } 
  406.  
  407.       public String getNameSpace() { 
  408.             return nameSpace; 
  409.       } 
  410.  
  411.       public void setNameSpace(String nameSpace) { 
  412.             this.nameSpace = nameSpace; 
  413.       } 
  414.  
  415.       public void calcCheckSum(){ 
  416.             this.checkSum = String.valueOf(this.time+this.nameSpace).hashCode(); 
  417.       } 
  418.      
  419.       public void setCheckSum(long checkSum){ 
  420.             //this should only be called before the package is sent 
  421.             this.checkSum = checkSum; 
  422.       } 
  423.        
  424.        
  425.       public long getCheckSum(){ 
  426.             //this should only be called before the package is sent 
  427.             //this.checkSum = String.valueOf(this.time+this.nameSpace).hashCode(); 
  428.             return this.checkSum; 
  429.       } 
  430.  
  431.       public long getTime() { 
  432.             return time; 
  433.       } 
  434.  
  435.       public void setTime(long time) { 
  436.             this.time = time; 
  437.       } 
  438.