Subversion Repositories FlightCtrl

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
403 ligi 1
/********************************************************************************************************************************
231 ligi 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
 *
403 ligi 7
 * see README for further Infos
8
 *
9
 *
10
 *******************************************************************************************************************************/
164 ligi 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
 
208 ligi 25
    public MKLCD LCD;
210 ligi 26
    public MKVersion version;
27
    public MKDebugData debug_data;
303 ligi 28
    public MKParamsParser params;
221 ligi 29
    public MKWatchDog watchdog;
314 ligi 30
    public MKProxy proxy=null;
208 ligi 31
 
181 ligi 32
    public long connection_start_time=-1;
164 ligi 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
 
208 ligi 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;
303 ligi 49
    public int params_data_count=0;
164 ligi 50
 
51
 
314 ligi 52
 
303 ligi 53
    String name;
54
 
164 ligi 55
    /******************  Section: public Methods ************************************************/
303 ligi 56
    public MKCommunicator()  
164 ligi 57
    {
210 ligi 58
        version=new MKVersion();
181 ligi 59
        debug_data=new MKDebugData();
303 ligi 60
        params=new MKParamsParser();
61
        //      mk_url=url; // remember URL for connecting / reconnecting later
181 ligi 62
 
303 ligi 63
                LCD= new MKLCD(this);
64
                watchdog=new MKWatchDog(this);
164 ligi 65
        new Thread( this ).start(); // fire up main Thread 
66
    }
67
 
68
 
314 ligi 69
    public void do_proxy(String proxy_url)
70
    {
71
        proxy=new MKProxy(proxy_url);
72
    }
303 ligi 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;
78
        name=_name;
79
        force_disconnect=false;
80
        connected=false;
81
    }
82
 
164 ligi 83
    /******************  Section: private Methods ************************************************/
84
    private void connect()
85
    {
303 ligi 86
 
164 ligi 87
        try{
88
                connection = (StreamConnection) Connector.open(mk_url, Connector.READ_WRITE);
89
                reader=connection.openInputStream();
90
                writer=connection.openOutputStream();
181 ligi 91
 
92
                connection_start_time=System.currentTimeMillis();
164 ligi 93
                connected=true; // if we get here everything seems to be OK
181 ligi 94
                get_version();
221 ligi 95
                lcd_data_count=0;
96
                debug_data_count=0;
97
                version_data_count=0;
98
 
303 ligi 99
 
164 ligi 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
            }  
181 ligi 106
 
107
 
108
 
164 ligi 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
 
325 ligi 142
    // FC - Function Mappers
164 ligi 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
 
303 ligi 150
    // send a MotorTest request - params are the speed for each Motor
231 ligi 151
    public void motor_test(int[] params)
152
    {
153
        send_command(0,'t',params);
154
    }
155
 
303 ligi 156
    // get params
157
    public void get_params(int id)
158
    {
159
        int[] params=new int[1];
160
        params[0]=id;
231 ligi 161
 
325 ligi 162
        while(sending)
163
            {try { Thread.sleep(50); }
164
            catch (Exception e)  {   }
165
            }
166
 
303 ligi 167
        send_command(0,'q',params);
168
    }
169
 
325 ligi 170
    public void trigger_LCD(int key)
171
    {
172
        if (sending) return;
303 ligi 173
 
325 ligi 174
 
175
        int[] params=new int[3];
176
        params[0]=key;
177
        params[1]=0;
178
        params[2]=0;
179
 
180
        send_command(0,'h',params);
181
 
182
    }
303 ligi 183
 
184
 
325 ligi 185
    public void write_params()
186
    {
187
        while(sending)
188
            {try { Thread.sleep(50); }
189
            catch (Exception e)  {   }
190
            }
191
 
192
        send_command(0,(char)('l'+params.act_paramset),params.field[params.act_paramset]);
193
    }
194
 
195
 
196
    boolean sending=false;
197
 
164 ligi 198
    // send command to FC ( add crc and pack into pseudo Base64
199
    public void send_command(int modul,char cmd,int[] params)
200
    {
325 ligi 201
        sending=true;
164 ligi 202
        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
203
        send_buff[0]='#';
204
        send_buff[1]=(char)modul;
205
        send_buff[2]=cmd;
206
 
208 ligi 207
        for(int param_pos=0;param_pos<(params.length/3 + (params.length%3==0?0:1)) ;param_pos++)
208
            {
231 ligi 209
                int a = (param_pos*3<params.length)?params[param_pos*3]:0;
210
                int b = ((param_pos*3+1)<params.length)?params[param_pos*3+1]:0;
211
                int c = ((param_pos*3+2)<params.length)?params[param_pos*3+2]:0;
208 ligi 212
 
213
                send_buff[3+param_pos*4] =  (char)((a >> 2)+'=' );
214
                send_buff[3+param_pos*4+1] = (char)('=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)));
215
                send_buff[3+param_pos*4+2] = (char)('=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)));
216
                send_buff[3+param_pos*4+3] = (char)('=' + ( c & 0x3f));
217
 
218
                //send_buff[3+foo]='=';
219
            }
220
 
221
/*      for(int foo=0;foo<(params.length/3 + (params.length%3==0?0:1) )*4;foo++)
222
            {
223
                int a = (foo<params.length) params[foo];
224
                int a = params[foo];
225
 
226
                //send_buff[3+foo]='=';
227
            }
228
*/
164 ligi 229
        try
230
            {
231
                int tmp_crc=0;
232
                for ( int tmp_i=0; tmp_i<send_buff.length;tmp_i++)
233
                    {
234
                        tmp_crc+=(int)send_buff[tmp_i];
235
                        writer.write(send_buff[tmp_i]);
236
                    }
237
                tmp_crc%=4096;
238
                writer.write( (char)(tmp_crc/64 + '='));
239
                writer.write( (char)(tmp_crc%64 + '='));
240
                writer.write('\r');
241
                writer.flush();
242
            }
243
        catch (Exception e)
244
            { // problem sending data to FC
245
            }
325 ligi 246
 
247
        sending=false;
164 ligi 248
    }
249
 
210 ligi 250
 
164 ligi 251
    public void process_data(int[] data,int len)
252
    {
253
        int[] decoded_data;
254
 
181 ligi 255
 
164 ligi 256
        switch((char)data[2])
257
            {
258
 
259
            case 'D': // debug Data
208 ligi 260
                debug_data_count++;
210 ligi 261
                debug_data.set_by_mk_data(Decode64(data,3,50),version);
164 ligi 262
                break;
263
 
264
            case 'V': // Version Info
208 ligi 265
                version_data_count++;
210 ligi 266
                version.set_by_mk_data(Decode64(data,3,6));
208 ligi 267
                break;
268
 
269
            case '0':
270
            case '1':
271
            case '2':
272
            case '3':
273
                LCD.handle_lcd_data(Decode64(data,3,20),data[2]-(int)'0');
274
                lcd_data_count++;
164 ligi 275
                break;
208 ligi 276
 
303 ligi 277
            case 'L':
278
            case 'M':
279
            case 'N':
280
            case 'O':
281
            case 'P':
314 ligi 282
                params.set_by_mk_data((int)(data[2]-'L'),Decode64(data,3,58),version);
303 ligi 283
                params_data_count++;
284
                break;
285
 
164 ligi 286
            default:
208 ligi 287
                other_data_count++;
164 ligi 288
                break;
289
 
290
            }
291
 
292
 
208 ligi 293
 
164 ligi 294
 
295
    }
296
 
208 ligi 297
    String o_msg="";
181 ligi 298
 
303 ligi 299
    public boolean force_disconnect=true;
181 ligi 300
 
221 ligi 301
    public void close_connections(boolean force)
208 ligi 302
    {
221 ligi 303
        force_disconnect=force;
208 ligi 304
        try{ reader.close(); }
305
        catch (Exception inner_ex) { }
181 ligi 306
 
208 ligi 307
        try{ writer.close(); }
308
        catch (Exception inner_ex) { }
309
 
310
        try{ connection.close(); }
311
        catch (Exception inner_ex) { }
312
 
313
        connected=false;
314
    }
315
 
164 ligi 316
    // Thread to recieve data from Connection
317
    public void run()
318
    {
319
        int[] data_set=new int[150];
320
        int input;
321
        int pos=0;
322
        msg+="!!run started!!";
323
        while(true)
324
            {
325
            if (!connected)
181 ligi 326
                {
208 ligi 327
                   if (!force_disconnect) connect();
181 ligi 328
                }
164 ligi 329
            else
330
                try{
181 ligi 331
 
164 ligi 332
                    pos=0;
333
                    input=0;
334
                    // recieve data-set
335
                    while ((input != 13)) // &&(input!=-1))
336
                       {
314 ligi 337
 
164 ligi 338
                           input = reader.read() ;
314 ligi 339
                           if (proxy!=null)
340
                               proxy.writer.write(input);
164 ligi 341
                           if (input==-1) throw new Exception("test");
342
                           data_set[pos]=input;
343
                           pos++;
344
 
345
                       }
314 ligi 346
 
347
                           if (proxy!=null)
348
                               {
349
                                proxy.writer.write('\r');
350
                                proxy.writer.write('\n');
351
                                proxy.writer.flush();
352
                               }
353
 
164 ligi 354
                    process_data(data_set,pos);
355
 
356
                   }
357
        catch (Exception ex)
358
            {
359
                msg="Problem reading from MK";
360
                // close the connection 
221 ligi 361
                close_connections(false);
208 ligi 362
 
363
 
164 ligi 364
            }  
365
 
366
            // sleep a bit to get someting more done
367
            try { Thread.sleep(50); }
368
            catch (Exception e)  {   }
369
 
370
            } // while
371
 
372
 
373
    } // run()
374
 
375
 
376
}