Subversion Repositories FlightCtrl

Rev

Rev 181 | 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
 
208 ligi 41
    public MKLCD LCD;
42
 
181 ligi 43
    public long connection_start_time=-1;
164 ligi 44
 
45
 
46
    /****************** Section: private Attributes **********************************************/
47
    private javax.microedition.io.StreamConnection connection;
48
    private java.io.InputStream reader;    
49
    private java.io.OutputStream writer;    
50
 
51
 
52
    // temp - to be removed
53
    String p_msg="--";
54
    public String msg="BT_INIT";
55
 
208 ligi 56
    public int debug_data_count=0;
57
    public int version_data_count=0;
58
    public int other_data_count=0;
59
    public int lcd_data_count=0;
164 ligi 60
 
61
 
62
    /******************  Section: public Methods ************************************************/
63
    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
64
    {
208 ligi 65
 
181 ligi 66
        debug_data=new MKDebugData();
164 ligi 67
        mk_url=url; // remember URL for connecting / reconnecting later
181 ligi 68
 
164 ligi 69
        new Thread( this ).start(); // fire up main Thread 
70
    }
71
 
72
 
73
    /******************  Section: private Methods ************************************************/
74
    private void connect()
75
    {
76
        try{
77
                connection = (StreamConnection) Connector.open(mk_url, Connector.READ_WRITE);
78
                reader=connection.openInputStream();
79
                writer=connection.openOutputStream();
181 ligi 80
 
81
                connection_start_time=System.currentTimeMillis();
164 ligi 82
                connected=true; // if we get here everything seems to be OK
181 ligi 83
                get_version();
208 ligi 84
                LCD= new MKLCD(this);
164 ligi 85
           }
86
        catch (Exception ex)
87
            {
88
                // TODO difference fatal errors from those which will lead to reconnection
89
                msg="Problem connecting" + "\n" + ex;
90
            }  
181 ligi 91
 
92
 
93
 
164 ligi 94
    }
95
 
96
 
97
 
98
    public int[] Decode64(int[] in_arr, int offset,int len)
99
    {
100
        int ptrIn=offset;      
101
        int a,b,c,d,x,y,z;
102
        int ptr=0;
103
 
104
        int[] out_arr=new int[len];
105
 
106
        while(len!=0)
107
            {
108
                a = in_arr[ptrIn++] - '=';
109
                b = in_arr[ptrIn++] - '=';
110
                c = in_arr[ptrIn++] - '=';
111
                d = in_arr[ptrIn++] - '=';
112
                //if(ptrIn > max - 2) break;     // nicht mehr Daten verarbeiten, als empfangen wurden
113
 
114
                x = (a << 2) | (b >> 4);
115
                y = ((b & 0x0f) << 4) | (c >> 2);
116
                z = ((c & 0x03) << 6) | d;
117
 
118
                if((len--)!=0) out_arr[ptr++] = x; else break;
119
                if((len--)!=0) out_arr[ptr++] = y; else break;
120
                if((len--)!=0) out_arr[ptr++] = z; else break;
121
            }
122
 
123
        return out_arr;
124
 
125
    }
126
 
127
 
128
    // send a version Request to the FC - the reply to this request will be processed in process_data when it arrives
129
    public void get_version()
130
    {
131
        send_command(0,'v',new int[0]);
132
    }
133
 
208 ligi 134
 
164 ligi 135
    // send command to FC ( add crc and pack into pseudo Base64
136
    public void send_command(int modul,char cmd,int[] params)
137
    {
138
        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
139
        send_buff[0]='#';
140
        send_buff[1]=(char)modul;
141
        send_buff[2]=cmd;
142
 
208 ligi 143
        for(int param_pos=0;param_pos<(params.length/3 + (params.length%3==0?0:1)) ;param_pos++)
144
            {
145
                int a = (param_pos<params.length)?params[param_pos]:0;
146
                int b = ((param_pos+1)<params.length)?params[param_pos+1]:0;
147
                int c = ((param_pos+2)<params.length)?params[param_pos+2]:0;
148
 
149
                send_buff[3+param_pos*4] =  (char)((a >> 2)+'=' );
150
                send_buff[3+param_pos*4+1] = (char)('=' + (((a & 0x03) << 4) | ((b & 0xf0) >> 4)));
151
                send_buff[3+param_pos*4+2] = (char)('=' + (((b & 0x0f) << 2) | ((c & 0xc0) >> 6)));
152
                send_buff[3+param_pos*4+3] = (char)('=' + ( c & 0x3f));
153
 
154
                //send_buff[3+foo]='=';
155
            }
156
 
157
/*      for(int foo=0;foo<(params.length/3 + (params.length%3==0?0:1) )*4;foo++)
158
            {
159
                int a = (foo<params.length) params[foo];
160
                int a = params[foo];
161
 
162
                //send_buff[3+foo]='=';
163
            }
164
*/
164 ligi 165
        try
166
            {
167
                int tmp_crc=0;
168
                for ( int tmp_i=0; tmp_i<send_buff.length;tmp_i++)
169
                    {
170
                        tmp_crc+=(int)send_buff[tmp_i];
171
                        writer.write(send_buff[tmp_i]);
172
                    }
173
                tmp_crc%=4096;
174
                writer.write( (char)(tmp_crc/64 + '='));
175
                writer.write( (char)(tmp_crc%64 + '='));
176
                writer.write('\r');
177
                writer.flush();
178
            }
179
        catch (Exception e)
180
            { // problem sending data to FC
181
            }
182
 
183
    }
184
 
185
    MKDebugData debug_data;
186
    public void process_data(int[] data,int len)
187
    {
188
        int[] decoded_data;
189
 
181 ligi 190
 
164 ligi 191
        switch((char)data[2])
192
            {
193
 
194
            case 'D': // debug Data
195
                decoded_data=Decode64(data,3,50);
196
                debug_data=new MKDebugData(decoded_data);
208 ligi 197
 
164 ligi 198
 
208 ligi 199
                debug_data_count++;
164 ligi 200
                break;
201
 
202
            case 'V': // Version Info
203
                decoded_data=Decode64(data,3,6);
204
                version_major=decoded_data[0];
205
                version_minor=decoded_data[1];
206
                version_compatible=decoded_data[2];
208 ligi 207
                version_data_count++;
208
 
209
                break;
210
 
211
            case '0':
212
            case '1':
213
            case '2':
214
            case '3':
215
                LCD.handle_lcd_data(Decode64(data,3,20),data[2]-(int)'0');
216
                lcd_data_count++;
217
                //              decoded_data=
164 ligi 218
 
208 ligi 219
 
220
                //              if ((data[2]-(int)'0')!=3) 
221
                //              get_LCD();
164 ligi 222
                break;
208 ligi 223
 
164 ligi 224
            default:
208 ligi 225
                other_data_count++;
164 ligi 226
                break;
227
 
228
            }
229
 
230
 
208 ligi 231
 
164 ligi 232
 
233
    }
234
 
208 ligi 235
    String o_msg="";
181 ligi 236
 
208 ligi 237
    public boolean force_disconnect=false;
181 ligi 238
 
208 ligi 239
    public void close_connections()
240
    {
241
        force_disconnect=true;
242
        try{ reader.close(); }
243
        catch (Exception inner_ex) { }
181 ligi 244
 
208 ligi 245
        try{ writer.close(); }
246
        catch (Exception inner_ex) { }
247
 
248
        try{ connection.close(); }
249
        catch (Exception inner_ex) { }
250
 
251
        connected=false;
252
    }
253
 
164 ligi 254
    // Thread to recieve data from Connection
255
    public void run()
256
    {
257
        int[] data_set=new int[150];
258
        int input;
259
        int pos=0;
260
        msg+="!!run started!!";
261
        while(true)
262
            {
263
            if (!connected)
181 ligi 264
                {
208 ligi 265
                   if (!force_disconnect) connect();
181 ligi 266
                }
164 ligi 267
            else
268
                try{
181 ligi 269
 
164 ligi 270
                    pos=0;
271
                    input=0;
272
                    // recieve data-set
273
                    while ((input != 13)) // &&(input!=-1))
274
                       {
275
                           input = reader.read() ;
276
                           if (input==-1) throw new Exception("test");
277
                           data_set[pos]=input;
278
                           pos++;
279
 
280
                       }
281
                    process_data(data_set,pos);
282
 
283
                   }
284
        catch (Exception ex)
285
            {
286
                msg="Problem reading from MK";
287
                // close the connection 
208 ligi 288
                close_connections();
289
 
290
 
164 ligi 291
            }  
292
 
293
            // sleep a bit to get someting more done
294
            try { Thread.sleep(50); }
295
            catch (Exception e)  {   }
296
 
297
            } // while
298
 
299
 
300
    } // run()
301
 
302
 
303
}