Subversion Repositories FlightCtrl

Rev

Rev 164 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
164 ligi 1
/*********************************************************************************************************************************
2
 *                                                                                                                                *
3
 * Abstaction Layer to Communicate via J2ME and Bluetooth with the FlightCtrl of the MikroKopter Project (www.mikrokopter.de )    *
4
 *                                                                                                                                *
5
 * Author:        Marcus -LiGi- Bueschleb                                                                                         *
6
 * Project-Start: 9/2007                                                                                                          *
7
 * Version:       0.07                                                                                                            *            
8
 * Mailto:        ligi@smart4mobile.de                                                                                            *
9
 * Licence:       Creative Commons / Non Commercial                                                                               *
10
 * Big Up:        Holger&Ingo                                                                                                     *
11
 * ChangeLog:                                                                                                                     *
12
 *              0.01 - initial Version ( initialize connection / main Thread with reading data from MK)                           *
13
 *              0.02 - reconnect after connection loss ( e.g. switching on/off )                                                  *
14
 *              0.03 - added send_command ( with CRC )                                                                            *
15
 *              0.04 - added decode64 to decode 'pseudo' BASE64                                                                   *
16
 *              0.05 - added get_version                                                                                          *
17
 *              0.06 - added parsing of DebugData                                                                                 *
18
 *              0.07 - Code-(Doc&&Cleanup) && initial svn commit                                                                  *                  
19
 *                                                                                                                                *
20
 *********************************************************************************************************************************/
21
 
22
import javax.microedition.io.*;
23
import java.io.*;
24
 
25
public class MKCommunicator
26
   implements Runnable
27
{
28
    /***************** Section: public Attributes **********************************************/
29
    public boolean connected=false; // flag for the connection state
30
    public boolean fatal=false; // flag which is set when an error is so fatal that reconnecting won't be tried - e.g. unknown version number.
31
 
32
 
33
    public String mk_url=""; // buffer the url which is given in the constuctor for reconnectin purposes
34
 
181 ligi 35
 
164 ligi 36
    // version Info from Flight Control
37
    public int version_major=-1;
38
    public int version_minor=-1;
39
    public int version_compatible=-1;
40
 
41
 
181 ligi 42
    public long connection_start_time=-1;
164 ligi 43
 
44
 
45
    /****************** Section: private Attributes **********************************************/
46
    private javax.microedition.io.StreamConnection connection;
47
    private java.io.InputStream reader;    
48
    private java.io.OutputStream writer;    
49
 
50
 
51
    // temp - to be removed
52
    String p_msg="--";
53
    public String msg="BT_INIT";
54
 
181 ligi 55
    public int data_count=0;
164 ligi 56
 
57
 
58
    /******************  Section: public Methods ************************************************/
59
    public MKCommunicator(String url)     // Constructor with URL string e.g. "btspp://XXXXXXXXXXXX:1" - the X-Part is the MAC-Adress of the Bluetooth-Device connected to the Fligth-Control
60
    {
181 ligi 61
        debug_data=new MKDebugData();
164 ligi 62
        mk_url=url; // remember URL for connecting / reconnecting later
181 ligi 63
 
164 ligi 64
        new Thread( this ).start(); // fire up main Thread 
65
    }
66
 
67
 
68
    /******************  Section: private Methods ************************************************/
69
    private void connect()
70
    {
71
        try{
72
                connection = (StreamConnection) Connector.open(mk_url, Connector.READ_WRITE);
73
                reader=connection.openInputStream();
74
                writer=connection.openOutputStream();
181 ligi 75
 
76
                connection_start_time=System.currentTimeMillis();
164 ligi 77
                connected=true; // if we get here everything seems to be OK
181 ligi 78
                get_version();
164 ligi 79
           }
80
        catch (Exception ex)
81
            {
82
                // TODO difference fatal errors from those which will lead to reconnection
83
                msg="Problem connecting" + "\n" + ex;
84
            }  
181 ligi 85
 
86
 
87
 
164 ligi 88
    }
89
 
90
 
91
 
92
    public int[] Decode64(int[] in_arr, int offset,int len)
93
    {
94
        int ptrIn=offset;      
95
        int a,b,c,d,x,y,z;
96
        int ptr=0;
97
 
98
        int[] out_arr=new int[len];
99
 
100
        while(len!=0)
101
            {
102
                a = in_arr[ptrIn++] - '=';
103
                b = in_arr[ptrIn++] - '=';
104
                c = in_arr[ptrIn++] - '=';
105
                d = in_arr[ptrIn++] - '=';
106
                //if(ptrIn > max - 2) break;     // nicht mehr Daten verarbeiten, als empfangen wurden
107
 
108
                x = (a << 2) | (b >> 4);
109
                y = ((b & 0x0f) << 4) | (c >> 2);
110
                z = ((c & 0x03) << 6) | d;
111
 
112
                if((len--)!=0) out_arr[ptr++] = x; else break;
113
                if((len--)!=0) out_arr[ptr++] = y; else break;
114
                if((len--)!=0) out_arr[ptr++] = z; else break;
115
            }
116
 
117
        return out_arr;
118
 
119
    }
120
 
121
 
122
    // send a version Request to the FC - the reply to this request will be processed in process_data when it arrives
123
    public void get_version()
124
    {
125
        send_command(0,'v',new int[0]);
126
    }
127
 
128
    // send command to FC ( add crc and pack into pseudo Base64
129
    public void send_command(int modul,char cmd,int[] params)
130
    {
131
        char[] send_buff=new char[5 + (params.length/3 + (params.length%3==0?0:1) )*4]; // 5=1*start_char+1*addr+1*cmd+2*crc
132
        send_buff[0]='#';
133
        send_buff[1]=(char)modul;
134
        send_buff[2]=cmd;
135
 
136
        try
137
            {
138
                int tmp_crc=0;
139
                for ( int tmp_i=0; tmp_i<send_buff.length;tmp_i++)
140
                    {
141
                        tmp_crc+=(int)send_buff[tmp_i];
142
                        writer.write(send_buff[tmp_i]);
143
                    }
144
                tmp_crc%=4096;
145
                writer.write( (char)(tmp_crc/64 + '='));
146
                writer.write( (char)(tmp_crc%64 + '='));
147
                writer.write('\r');
148
                writer.flush();
149
            }
150
        catch (Exception e)
151
            { // problem sending data to FC
152
            }
153
 
154
    }
155
 
156
    MKDebugData debug_data;
157
    public void process_data(int[] data,int len)
158
    {
159
        int[] decoded_data;
160
 
181 ligi 161
 
164 ligi 162
        switch((char)data[2])
163
            {
164
 
165
            case 'D': // debug Data
166
                decoded_data=Decode64(data,3,50);
167
                debug_data=new MKDebugData(decoded_data);
168
                msg="Got Debug Data s:" + debug_data.sekunden + "zy:"+debug_data.zyklen + "ze:" + debug_data.zeit + connected + ">" + data_count;
169
                for (int ff=0;ff<8;ff++)
170
                    msg+="\n  d:" + (ff*2+1) + " " + debug_data.analog[ff*2] + " d2:" + (ff*2+2) + " "  + debug_data.analog[ff*2+1] ;
171
 
172
                break;
173
 
174
            case 'V': // Version Info
175
                decoded_data=Decode64(data,3,6);
176
                version_major=decoded_data[0];
177
                version_minor=decoded_data[1];
178
                version_compatible=decoded_data[2];
179
 
180
                break;
181
 
182
            default:
183
                break;
184
 
185
            }
186
 
187
 
188
        msg+=p_msg;
189
        msg+="OK";
190
        data_count++;
191
 
192
    }
193
 
181 ligi 194
 
195
 
196
 
164 ligi 197
    // Thread to recieve data from Connection
198
    public void run()
199
    {
200
        int[] data_set=new int[150];
201
        int input;
202
        int pos=0;
203
        msg+="!!run started!!";
204
        while(true)
205
            {
206
            if (!connected)
181 ligi 207
                {
208
                    connect();
209
                }
164 ligi 210
            else
211
                try{
181 ligi 212
 
164 ligi 213
                    pos=0;
214
                    input=0;
215
                    // recieve data-set
216
                    while ((input != 13)) // &&(input!=-1))
217
                       {
218
                           input = reader.read() ;
219
                           if (input==-1) throw new Exception("test");
220
                           data_set[pos]=input;
221
                           pos++;
222
 
223
                       }
224
                    process_data(data_set,pos);
225
 
226
                   }
227
        catch (Exception ex)
228
            {
229
                msg="Problem reading from MK";
230
                // close the connection 
231
                try{ reader.close(); connection.close(); }
232
                catch (Exception inner_ex) { }
233
                connected=false;
234
            }  
235
 
236
            // sleep a bit to get someting more done
237
            try { Thread.sleep(50); }
238
            catch (Exception e)  {   }
239
 
240
            } // while
241
 
242
 
243
    } // run()
244
 
245
 
246
}