Subversion Repositories Projects

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 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
 *
7
 * see README for further Infos
8
 *
9
 *
10
 *******************************************************************************************************************************/
11
 
12
import javax.microedition.io.*;
13
import java.io.*;
14
 
15
public class MKCommunicator
16
   implements Runnable
17
{
18
    /***************** Section: public Attributes **********************************************/
19
    public boolean connected=false; // flag for the connection state
20
    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.
21
 
22
 
23
    public String mk_url=""; // buffer the url which is given in the constuctor for reconnectin purposes
24
 
25
    public MKLCD LCD;
26
    public MKVersion version;
27
    public MKDebugData debug_data;
28
    public MKParamsParser params;
29
    public MKWatchDog watchdog;
30
    public MKProxy proxy=null;
31
 
32
    public long connection_start_time=-1;
33
 
34
 
35
    /****************** Section: private Attributes **********************************************/
36
    private javax.microedition.io.StreamConnection connection;
37
    private java.io.InputStream reader;    
38
    private java.io.OutputStream writer;    
39
 
40
 
41
    // temp - to be removed
42
    String p_msg="--";
43
    public String msg="BT_INIT";
44
 
45
    public int debug_data_count=0;
46
    public int version_data_count=0;
47
    public int other_data_count=0;
48
    public int lcd_data_count=0;
49
    public int params_data_count=0;
50
 
51
 
52
 
53
    String name;
54
    DUBwise root;
55
 
56
    /******************  Section: public Methods ************************************************/
57
    public MKCommunicator(DUBwise root_)  
58
    {
59
        root=root_;
60
        version=new MKVersion();
61
        debug_data=new MKDebugData();
62
        params=new MKParamsParser();
63
        LCD= new MKLCD(this);
64
        watchdog=new MKWatchDog(this);
65
        new Thread( this ).start(); // fire up main Thread 
66
    }
67
 
68
 
69
    public void do_proxy(String proxy_url)
70
    {
71
        proxy=new MKProxy(proxy_url);
72
    }
73
 
74
    //  URL string: "btspp://XXXXXXXXXXXX:1" - the X-Part is the MAC-Adress of the Bluetooth-Device connected to the Fligth-Control
75
    public void connect_to(String _url,String _name)
76
    {
77
        mk_url=_url; // remember URL for connecting / reconnecting later
78
        name=_name;
79
        force_disconnect=false;
80
        connected=false;
81
    }
82
 
83
    /******************  Section: private Methods ************************************************/
84
    private void connect()
85
    {
86
 
87
        try{
88
                connection = (StreamConnection) Connector.open(mk_url, Connector.READ_WRITE);
89
                reader=connection.openInputStream();
90
                writer=connection.openOutputStream();
91
 
92
                connection_start_time=System.currentTimeMillis();
93
                connected=true; // if we get here everything seems to be OK
94
                get_version();
95
                lcd_data_count=0;
96
                debug_data_count=0;
97
                version_data_count=0;
98
 
99
 
100
           }
101
        catch (Exception ex)
102
            {
103
                // TODO difference fatal errors from those which will lead to reconnection
104
                msg="Problem connecting" + "\n" + ex;
105
            }  
106
 
107
 
108
 
109
    }
110
 
111
 
112
 
113
    public int[] Decode64(int[] in_arr, int offset,int len)
114
    {
115
        int ptrIn=offset;      
116
        int a,b,c,d,x,y,z;
117
        int ptr=0;
118
 
119
        int[] out_arr=new int[len];
120
 
121
        while(len!=0)
122
            {
123
                a = in_arr[ptrIn++] - '=';
124
                b = in_arr[ptrIn++] - '=';
125
                c = in_arr[ptrIn++] - '=';
126
                d = in_arr[ptrIn++] - '=';
127
                //if(ptrIn > max - 2) break;     // nicht mehr Daten verarbeiten, als empfangen wurden
128
 
129
                x = (a << 2) | (b >> 4);
130
                y = ((b & 0x0f) << 4) | (c >> 2);
131
                z = ((c & 0x03) << 6) | d;
132
 
133
                if((len--)!=0) out_arr[ptr++] = x; else break;
134
                if((len--)!=0) out_arr[ptr++] = y; else break;
135
                if((len--)!=0) out_arr[ptr++] = z; else break;
136
            }
137
 
138
        return out_arr;
139
 
140
    }
141
 
142
    // FC - Function Mappers
143
 
144
    // send a version Request to the FC - the reply to this request will be processed in process_data when it arrives
145
    public void get_version()
146
    {
147
        send_command(0,'v',new int[0]);
148
    }
149
 
150
    // send a MotorTest request - params are the speed for each Motor
151
    public void motor_test(int[] params)
152
    {
153
        send_command(0,'t',params);
154
    }
155
 
156
    public void send_keys(int[] params)
157
    {
158
        send_command(0,'k',params);
159
    }
160
 
161
    // get params
162
    public void get_params(int id)
163
    {
164
        int[] params=new int[1];
165
        params[0]=id;
166
 
167
        while(sending)
168
            {try { Thread.sleep(50); }
169
            catch (Exception e)  {   }
170
            }
171
 
172
        send_command(0,'q',params);
173
    }
174
 
175
 
176
    public void get_debug_name(int id)
177
    {
178
        int[] params=new int[1];
179
        params[0]=id;
180
 
181
        while(sending)
182
            {try { Thread.sleep(50); }
183
            catch (Exception e)  {   }
184
            }
185
 
186
        send_command(0,'a',params);
187
    }
188
 
189
 
190
 
191
 
192
   public void trigger_LCD(int key)
193
    {
194
        if (sending) return;
195
 
196
 
197
        int[] params=new int[3];
198
        params[0]=key;
199
        params[1]=0;
200
        params[2]=0;
201
 
202
        send_command(0,'h',params);
203
 
204
    }
205
 
206
 
207
    public void write_params()
208
    {
209
        while(sending)
210
            {try { Thread.sleep(50); }
211
            catch (Exception e)  {   }
212
            }
213
 
214
        send_command(0,(char)('l'+params.act_paramset),params.field[params.act_paramset]);
215
    }
216
 
217
 
218
    boolean sending=false;
219
 
220
    // send command to FC ( add crc and pack into pseudo Base64
221
    public void send_command(int modul,char cmd,int[] params)
222
    {
223
        sending=true;
224
        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
225
        send_buff[0]='#';
226
        send_buff[1]=(char)modul;
227
        send_buff[2]=cmd;
228
 
229
        for(int param_pos=0;param_pos<(params.length/3 + (params.length%3==0?0:1)) ;param_pos++)
230
            {
231
                int a = (param_pos*3<params.length)?params[param_pos*3]:0;
232
                int b = ((param_pos*3+1)<params.length)?params[param_pos*3+1]:0;
233
                int c = ((param_pos*3+2)<params.length)?params[param_pos*3+2]:0;
234
 
235
                send_buff[3+param_pos*4] =  (char)((a >> 2)+'=' );
236
                send_buff[3+param_pos*4+1] = (char)('=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)));
237
                send_buff[3+param_pos*4+2] = (char)('=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)));
238
                send_buff[3+param_pos*4+3] = (char)('=' + ( c & 0x3f));
239
 
240
                //send_buff[3+foo]='=';
241
            }
242
 
243
/*      for(int foo=0;foo<(params.length/3 + (params.length%3==0?0:1) )*4;foo++)
244
            {
245
                int a = (foo<params.length) params[foo];
246
                int a = params[foo];
247
 
248
                //send_buff[3+foo]='=';
249
            }
250
*/
251
        try
252
            {
253
                int tmp_crc=0;
254
                for ( int tmp_i=0; tmp_i<send_buff.length;tmp_i++)
255
                    {
256
                        tmp_crc+=(int)send_buff[tmp_i];
257
                        writer.write(send_buff[tmp_i]);
258
                    }
259
                tmp_crc%=4096;
260
                writer.write( (char)(tmp_crc/64 + '='));
261
                writer.write( (char)(tmp_crc%64 + '='));
262
                writer.write('\r');
263
                writer.flush();
264
            }
265
        catch (Exception e)
266
            { // problem sending data to FC
267
            }
268
 
269
        sending=false;
270
    }
271
 
272
 
273
    public void process_data(int[] data,int len)
274
    {
275
        int[] decoded_data;
276
 
277
 
278
        switch((char)data[2])
279
            {
280
 
281
            case 'D': // debug Data
282
                debug_data_count++;
283
                debug_data.set_by_mk_data(Decode64(data,3,len-3),version);
284
                break;
285
 
286
            case 'A': // debug Data Names
287
                //debug_data_count++;
288
                debug_data.set_names_by_mk_data(data[1]-'0',Decode64(data,3,len-3));
289
                break;
290
 
291
            case 'V': // Version Info
292
                version_data_count++;
293
                version.set_by_mk_data(Decode64(data,3,6));
294
                break;
295
 
296
            case '0':
297
            case '1':
298
            case '2':
299
            case '3':
300
                LCD.handle_lcd_data(Decode64(data,3,20),data[2]-(int)'0');
301
                lcd_data_count++;
302
                break;
303
 
304
            case 'L':
305
            case 'M':
306
            case 'N':
307
            case 'O':
308
            case 'P':
309
                params.set_by_mk_data((int)(data[2]-'L'),Decode64(data,3,len-3),version);
310
                params_data_count++;
311
                break;
312
 
313
            default:
314
                other_data_count++;
315
                break;
316
 
317
            }
318
 
319
 
320
 
321
 
322
    }
323
 
324
    String o_msg="";
325
 
326
    public boolean force_disconnect=true;
327
 
328
    public void close_connections(boolean force)
329
    {
330
        if (!force) root.vibrate(500);
331
        force_disconnect=force;
332
        try{ reader.close(); }
333
        catch (Exception inner_ex) { }
334
 
335
        try{ writer.close(); }
336
        catch (Exception inner_ex) { }
337
 
338
        try{ connection.close(); }
339
        catch (Exception inner_ex) { }
340
 
341
        connected=false;
342
    }
343
 
344
    // Thread to recieve data from Connection
345
    public void run()
346
    {
347
        int[] data_set=new int[150];
348
        int input;
349
        int pos=0;
350
        msg+="!!run started!!";
351
        while(true)
352
            {
353
            if (!connected)
354
                {
355
                   if (!force_disconnect) connect();
356
                }
357
            else
358
                try{
359
 
360
                    pos=0;
361
                    input=0;
362
                    // recieve data-set
363
                    while ((input != 13)) // &&(input!=-1))
364
                       {
365
 
366
                           input = reader.read() ;
367
                           if (proxy!=null)
368
                               proxy.writer.write(input);
369
                           if (input==-1) throw new Exception("test");
370
                           data_set[pos]=input;
371
                           pos++;
372
 
373
                       }
374
 
375
                           if (proxy!=null)
376
                               {
377
                                proxy.writer.write('\r');
378
                                proxy.writer.write('\n');
379
                                proxy.writer.flush();
380
                               }
381
 
382
                    process_data(data_set,pos);
383
 
384
                   }
385
        catch (Exception ex)
386
            {
387
                msg="Problem reading from MK";
388
                // close the connection 
389
                close_connections(false);
390
 
391
 
392
            }  
393
 
394
            // sleep a bit to get someting more done
395
            try { Thread.sleep(50); }
396
            catch (Exception e)  {   }
397
 
398
            } // while
399
 
400
 
401
    } // run()
402
 
403
 
404
}