iiii
This commit is contained in:
		
							parent
							
								
									e2fded1068
								
							
						
					
					
						commit
						0459ddc966
					
				
					 7 changed files with 261 additions and 193 deletions
				
			
		| 
						 | 
				
			
			@ -80,27 +80,14 @@
 | 
			
		|||
      <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
 | 
			
		||||
      <sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
 | 
			
		||||
      <sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-safeguard" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-verifier" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-resources" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
 | 
			
		||||
      <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
 | 
			
		||||
    </content>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,8 @@ import android.widget.Toast;
 | 
			
		|||
import com.example.android.bluetoothchat.R;
 | 
			
		||||
import org.surfsite.iconsole.common.logger.Log;
 | 
			
		||||
 | 
			
		||||
import java.util.Locale;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This fragment controls Bluetooth to communicate with other devices.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -59,8 +61,9 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
 | 
			
		||||
    // Layout Views
 | 
			
		||||
    private ListView mConversationView;
 | 
			
		||||
    private EditText mOutEditText;
 | 
			
		||||
    private Button mSendButton;
 | 
			
		||||
    private Button mStartButton;
 | 
			
		||||
    private Button mStopButton;
 | 
			
		||||
    private Button mDisconnectButton;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Name of the connected device
 | 
			
		||||
| 
						 | 
				
			
			@ -72,11 +75,6 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
     */
 | 
			
		||||
    private ArrayAdapter<String> mConversationArrayAdapter;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * String buffer for outgoing messages
 | 
			
		||||
     */
 | 
			
		||||
    private StringBuffer mOutStringBuffer;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Local Bluetooth adapter
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			@ -150,8 +148,9 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
    @Override
 | 
			
		||||
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
 | 
			
		||||
        mConversationView = (ListView) view.findViewById(R.id.in);
 | 
			
		||||
        mOutEditText = (EditText) view.findViewById(R.id.edit_text_out);
 | 
			
		||||
        mSendButton = (Button) view.findViewById(R.id.button_send);
 | 
			
		||||
        mStartButton = (Button) view.findViewById(R.id.button_start);
 | 
			
		||||
        mStopButton = (Button) view.findViewById(R.id.button_stop);
 | 
			
		||||
        mDisconnectButton = (Button) view.findViewById(R.id.button_disconnect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -165,27 +164,30 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
 | 
			
		||||
        mConversationView.setAdapter(mConversationArrayAdapter);
 | 
			
		||||
 | 
			
		||||
        // Initialize the compose field with a listener for the return key
 | 
			
		||||
        mOutEditText.setOnEditorActionListener(mWriteListener);
 | 
			
		||||
 | 
			
		||||
        // Initialize the send button with a listener that for click events
 | 
			
		||||
        mSendButton.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                // Send a message using content of the edit text widget
 | 
			
		||||
                View view = getView();
 | 
			
		||||
                if (null != view) {
 | 
			
		||||
                    TextView textView = (TextView) view.findViewById(R.id.edit_text_out);
 | 
			
		||||
                    String message = textView.getText().toString();
 | 
			
		||||
                    sendMessage(message);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Initialize the BluetoothChatService to perform bluetooth connections
 | 
			
		||||
        mChatService = new BluetoothChatService(getActivity(), mHandler);
 | 
			
		||||
 | 
			
		||||
        // Initialize the buffer for outgoing messages
 | 
			
		||||
        mOutStringBuffer = new StringBuffer("");
 | 
			
		||||
        mStartButton.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                    mChatService.startIConsole();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        mStopButton.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                mChatService.stopIConsole();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        mDisconnectButton.setOnClickListener(new View.OnClickListener() {
 | 
			
		||||
            public void onClick(View v) {
 | 
			
		||||
                mChatService.stop();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        mStartButton.setEnabled(false);
 | 
			
		||||
        mStopButton.setEnabled(false);
 | 
			
		||||
        mDisconnectButton.setEnabled(false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -212,32 +214,8 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check that there's actually something to send
 | 
			
		||||
        if (message.length() > 0) {
 | 
			
		||||
            // Get the message bytes and tell the BluetoothChatService to write
 | 
			
		||||
            byte[] send = message.getBytes();
 | 
			
		||||
            mChatService.write(send);
 | 
			
		||||
 | 
			
		||||
            // Reset out string buffer to zero and clear the edit text field
 | 
			
		||||
            mOutStringBuffer.setLength(0);
 | 
			
		||||
            mOutEditText.setText(mOutStringBuffer);
 | 
			
		||||
        mChatService.startIConsole();
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The action listener for the EditText widget, to listen for the return key
 | 
			
		||||
     */
 | 
			
		||||
    private TextView.OnEditorActionListener mWriteListener
 | 
			
		||||
            = new TextView.OnEditorActionListener() {
 | 
			
		||||
        public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
 | 
			
		||||
            // If the action is a key-up event on the return key, send the message
 | 
			
		||||
            if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
 | 
			
		||||
                String message = view.getText().toString();
 | 
			
		||||
                sendMessage(message);
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Updates the status on the action bar.
 | 
			
		||||
| 
						 | 
				
			
			@ -286,16 +264,32 @@ public class BluetoothChatFragment extends Fragment {
 | 
			
		|||
                        case BluetoothChatService.STATE_CONNECTED:
 | 
			
		||||
                            setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
 | 
			
		||||
                            mConversationArrayAdapter.clear();
 | 
			
		||||
                            mStartButton.setEnabled(true);
 | 
			
		||||
                            mStopButton.setEnabled(true);
 | 
			
		||||
                            mDisconnectButton.setEnabled(true);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case BluetoothChatService.STATE_CONNECTING:
 | 
			
		||||
                            setStatus(R.string.title_connecting);
 | 
			
		||||
                            mStartButton.setEnabled(false);
 | 
			
		||||
                            mStopButton.setEnabled(false);
 | 
			
		||||
                            mDisconnectButton.setEnabled(false);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case BluetoothChatService.STATE_LISTEN:
 | 
			
		||||
                        case BluetoothChatService.STATE_NONE:
 | 
			
		||||
                            setStatus(R.string.title_not_connected);
 | 
			
		||||
                            mStartButton.setEnabled(false);
 | 
			
		||||
                            mStopButton.setEnabled(false);
 | 
			
		||||
                            mDisconnectButton.setEnabled(false);
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                    break;
 | 
			
		||||
                case Constants.MESSAGE_DATA:
 | 
			
		||||
                    IConsole.Data data = (IConsole.Data) msg.obj;
 | 
			
		||||
                    String dataMessage = String.format(Locale.US, "Time: %s Speed: %f Power: %f RPM: %d LVL: %d Dist: %f Cal: %d HF: %d",
 | 
			
		||||
                            data.mTime, data.mSpeed10 / 10.0, data.mPower10 / 10.0, data.mRPM,
 | 
			
		||||
                            data.mLevel, data.mDistance10 / 10.0, data.mCalories, data.mHF);
 | 
			
		||||
                    mConversationArrayAdapter.add(mConnectedDeviceName + ":  " + dataMessage);
 | 
			
		||||
                    break;
 | 
			
		||||
                case Constants.MESSAGE_WRITE:
 | 
			
		||||
                    byte[] writeBuf = (byte[]) msg.obj;
 | 
			
		||||
                    // construct a string from the buffer
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -203,13 +203,12 @@ public class BluetoothChatService {
 | 
			
		|||
        updateUserInterfaceTitle();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Write to the ConnectedThread in an unsynchronized manner
 | 
			
		||||
     *
 | 
			
		||||
     * @param out The bytes to write
 | 
			
		||||
     * @see ConnectedThread#write(byte[])
 | 
			
		||||
     */
 | 
			
		||||
    public void write(byte[] out) {
 | 
			
		||||
    public synchronized boolean startIConsole() {
 | 
			
		||||
        return mConnectedThread.startIConsole();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public synchronized boolean stopIConsole() {
 | 
			
		||||
        return mConnectedThread.startIConsole();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -346,8 +345,10 @@ public class BluetoothChatService {
 | 
			
		|||
            mmIConsole = new IConsole(mmInStream, mmOutStream, new IConsole.DataListener() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onData(IConsole.Data data) {
 | 
			
		||||
                    Log.i(TAG, "mConnectedThread: " + data.toString());
 | 
			
		||||
                    /* print */
 | 
			
		||||
                    Log.i(TAG, "mConnectedThread: onData");
 | 
			
		||||
                    // Share the sent message back to the UI Activity
 | 
			
		||||
                    mHandler.obtainMessage(Constants.MESSAGE_DATA, -1, -1, data)
 | 
			
		||||
                            .sendToTarget();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +362,7 @@ public class BluetoothChatService {
 | 
			
		|||
                @Override
 | 
			
		||||
                public void onRead(byte[] buffer) {
 | 
			
		||||
                    if (buffer.length > 0) {
 | 
			
		||||
                        String hexbuf = IConsole.byteArrayToHex(Arrays.copyOfRange(buffer, 0, buffer.length)) + '\n';
 | 
			
		||||
                        String hexbuf = IConsole.byteArrayToHex(Arrays.copyOfRange(buffer, 0, buffer.length));
 | 
			
		||||
 | 
			
		||||
                        // Send the obtained bytes to the UI Activity
 | 
			
		||||
                        mHandler.obtainMessage(Constants.MESSAGE_READ, hexbuf.length(), -1, hexbuf.getBytes())
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +372,7 @@ public class BluetoothChatService {
 | 
			
		|||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onWrite(byte[] buffer) {
 | 
			
		||||
                    String hexbuf = IConsole.byteArrayToHex(buffer) + '\n';
 | 
			
		||||
                    String hexbuf = IConsole.byteArrayToHex(buffer);
 | 
			
		||||
 | 
			
		||||
                    // Share the sent message back to the UI Activity
 | 
			
		||||
                    mHandler.obtainMessage(Constants.MESSAGE_WRITE, -1, -1, hexbuf.getBytes())
 | 
			
		||||
| 
						 | 
				
			
			@ -383,15 +384,25 @@ public class BluetoothChatService {
 | 
			
		|||
        public void run() {
 | 
			
		||||
            Log.i(TAG, "BEGIN mConnectedThread");
 | 
			
		||||
 | 
			
		||||
            mmIConsole.start();
 | 
			
		||||
 | 
			
		||||
            while (mState == STATE_CONNECTED) {
 | 
			
		||||
                if (!mmIConsole.processIO())
 | 
			
		||||
                    break;
 | 
			
		||||
                try {
 | 
			
		||||
                    Thread.sleep(100);
 | 
			
		||||
                } catch (InterruptedException e) {
 | 
			
		||||
                    ; // ignore
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public boolean setLevel(int level) {
 | 
			
		||||
            return mmIConsole.setLevel(level);
 | 
			
		||||
        }
 | 
			
		||||
        public boolean startIConsole() { return mmIConsole.start(); }
 | 
			
		||||
        public boolean stopIConsole() { return mmIConsole.stop(); }
 | 
			
		||||
 | 
			
		||||
        public void cancel() {
 | 
			
		||||
            mmIConsole.stop();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@ public interface Constants {
 | 
			
		|||
    public static final int MESSAGE_WRITE = 3;
 | 
			
		||||
    public static final int MESSAGE_DEVICE_NAME = 4;
 | 
			
		||||
    public static final int MESSAGE_TOAST = 5;
 | 
			
		||||
    public static final int MESSAGE_DATA = 6;
 | 
			
		||||
 | 
			
		||||
    // Key names received from the BluetoothChatService Handler
 | 
			
		||||
    public static final String DEVICE_NAME = "device_name";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,10 @@
 | 
			
		|||
package org.surfsite.iconsole;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.io.InputStream;
 | 
			
		||||
import java.io.OutputStream;
 | 
			
		||||
import java.util.Arrays;
 | 
			
		||||
import java.util.concurrent.TimeoutException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Created by harald on 25.04.17.
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +13,7 @@ import java.io.OutputStream;
 | 
			
		|||
class IConsole {
 | 
			
		||||
    private static final byte[] PING     = {(byte) 0xf0, (byte) 0xa0, (byte) 0x01, (byte) 0x01, (byte) 0x92 };
 | 
			
		||||
    private static final byte[] INIT_A0  = {(byte) 0xf0, (byte) 0xa0, 0x02, 0x02, (byte) 0x94};
 | 
			
		||||
    private static final byte[] PONG     = {(byte) 0xf0, (byte) 0xb0, 0x01, 0x01, (byte) 0xa2};
 | 
			
		||||
    //private static final byte[] PONG     = {(byte) 0xf0, (byte) 0xb0, 0x01, 0x01, (byte) 0xa2};
 | 
			
		||||
    private static final byte[] STATUS   = {(byte) 0xf0, (byte) 0xa1, 0x01, 0x01, (byte) 0x93};
 | 
			
		||||
    private static final byte[] INIT_A3  = {(byte) 0xf0, (byte) 0xa3, 0x01, 0x01, 0x01, (byte) 0x96};
 | 
			
		||||
    private static final byte[] INIT_A4  = {(byte) 0xf0, (byte) 0xa4, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, (byte) 0xa0};
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +27,7 @@ class IConsole {
 | 
			
		|||
        PING,
 | 
			
		||||
        A0,
 | 
			
		||||
        A1,
 | 
			
		||||
        A1_POST_PING,
 | 
			
		||||
        A3,
 | 
			
		||||
        A4,
 | 
			
		||||
        START,
 | 
			
		||||
| 
						 | 
				
			
			@ -32,9 +36,13 @@ class IConsole {
 | 
			
		|||
        SETLEVEL,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private State mCurrentState;
 | 
			
		||||
    private State mNextState;
 | 
			
		||||
    private int mSetLevel;
 | 
			
		||||
    private State mCurrentState = State.BEGIN;
 | 
			
		||||
    private State mNextState = State.PING;
 | 
			
		||||
    private boolean mWaitAck = false;
 | 
			
		||||
    private int mSetLevel = 1;
 | 
			
		||||
    private long mTimesent = 0;
 | 
			
		||||
    private int mExpectLen = 0;
 | 
			
		||||
    private byte[] mExpectPacket;
 | 
			
		||||
    private final InputStream mInputStream;
 | 
			
		||||
    private final OutputStream mOutputStream;
 | 
			
		||||
    private final DataListener mDataListener;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,12 +53,9 @@ class IConsole {
 | 
			
		|||
        this.mOutputStream = outputStream;
 | 
			
		||||
        this.mDataListener = dataListener;
 | 
			
		||||
        this.mDebugListener = debugListener;
 | 
			
		||||
        this.mCurrentState = State.BEGIN;
 | 
			
		||||
        this.mNextState = State.PING;
 | 
			
		||||
        this.mSetLevel = 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class Data {
 | 
			
		||||
    class Data implements java.io.Serializable {
 | 
			
		||||
        long mTime;         // in seconds
 | 
			
		||||
        int mSpeed10;
 | 
			
		||||
        int mRPM;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,21 +98,17 @@ class IConsole {
 | 
			
		|||
        void onWrite(byte[] bytes);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean processIO() {
 | 
			
		||||
    boolean start() {
 | 
			
		||||
        synchronized (this) {
 | 
			
		||||
            Data data = new Data(0, 0, 0, 0, 0, 0, 0, 0);
 | 
			
		||||
 | 
			
		||||
            if (null != mDebugListener) {
 | 
			
		||||
                mDebugListener.onWrite(PING);
 | 
			
		||||
                mDebugListener.onRead(PONG);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            mDataListener.onData(data);
 | 
			
		||||
            this.mNextState = State.A0;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean stop() {
 | 
			
		||||
        synchronized (this) {
 | 
			
		||||
            this.mNextState = State.STOP;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -116,121 +117,190 @@ class IConsole {
 | 
			
		|||
            if (mCurrentState != State.READ)
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
            this.mCurrentState = State.SETLEVEL;
 | 
			
		||||
            this.mNextState = State.READ;
 | 
			
		||||
            this.mNextState = State.SETLEVEL;
 | 
			
		||||
            this.mSetLevel = level;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
    def send_ack(packet, expect=None, plen=0):
 | 
			
		||||
    if expect == None:
 | 
			
		||||
        expect = 0xb0 | (ord(packet[1]) & 0xF)
 | 
			
		||||
    boolean send(byte[] packet, byte expect, int plen) throws IOException {
 | 
			
		||||
        long now = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
    if plen == 0:
 | 
			
		||||
        plen = len(packet)
 | 
			
		||||
        if ((now - mTimesent) < 200) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    got = None
 | 
			
		||||
    while got == None:
 | 
			
		||||
        sleep(0.1)
 | 
			
		||||
        sock.sendall(packet)
 | 
			
		||||
        i = 0
 | 
			
		||||
        while got == None and i < 6:
 | 
			
		||||
            i+=1
 | 
			
		||||
            sleep(0.1)
 | 
			
		||||
            got = sock.recv(plen)
 | 
			
		||||
            if len(got) == plen:
 | 
			
		||||
                #print "<-" + hexlify(got)
 | 
			
		||||
                pass
 | 
			
		||||
            else:
 | 
			
		||||
                if len(got) > 0:
 | 
			
		||||
                    #print "Got len == %d" % len(got)
 | 
			
		||||
                    pass
 | 
			
		||||
                got = None
 | 
			
		||||
        // Flush input stream
 | 
			
		||||
        try {
 | 
			
		||||
            mInputStream.skip(mInputStream.available());
 | 
			
		||||
        } catch (IOException e) {
 | 
			
		||||
            ; // ignore
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if got and len(got) >= 3 and got[0] == packet[0] and ord(got[1]) == expect:
 | 
			
		||||
            break
 | 
			
		||||
        got = None
 | 
			
		||||
        #print "---> Retransmit"
 | 
			
		||||
    return got
 | 
			
		||||
        // Send packet
 | 
			
		||||
        mOutputStream.write(packet);
 | 
			
		||||
 | 
			
		||||
def send_level(lvl):
 | 
			
		||||
    packet = struct.pack('BBBBBB', 0xf0, 0xa6, 0x01, 0x01, lvl+1, (0xf0+0xa6+3+lvl) & 0xFF)
 | 
			
		||||
    got = send_ack(packet)
 | 
			
		||||
    return got
 | 
			
		||||
        if (null != mDataListener)
 | 
			
		||||
            mDebugListener.onWrite(packet);
 | 
			
		||||
 | 
			
		||||
     */
 | 
			
		||||
        mTimesent = System.currentTimeMillis();
 | 
			
		||||
        mExpectPacket = packet;
 | 
			
		||||
        mExpectPacket[1] = expect;
 | 
			
		||||
        mExpectLen = plen;
 | 
			
		||||
        mWaitAck = true;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    send_ack(PING)
 | 
			
		||||
    prints(win, "ping done")
 | 
			
		||||
    private boolean send(byte[] packet) throws IOException {
 | 
			
		||||
        return send(packet, (byte)(0xb0 | (packet[1] & 0xF)), packet.length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    send_ack(INIT_A0, expect=0xb7, plen=6)
 | 
			
		||||
    prints(win, "A0 done")
 | 
			
		||||
    private boolean send(byte[] packet, int plen) throws IOException {
 | 
			
		||||
        return send(packet, (byte)(0xb0 | (packet[1] & 0xF)), plen);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for i in range(0, 5):
 | 
			
		||||
        send_ack(PING)
 | 
			
		||||
        prints(win, "ping done")
 | 
			
		||||
    private boolean send_level(int level) throws IOException {
 | 
			
		||||
        byte[] packet = SETLEVEL.clone();
 | 
			
		||||
        packet[4] = (byte) (packet[4] + level);
 | 
			
		||||
        packet[5] = (byte) ((packet[5] + level) & 0xFF);
 | 
			
		||||
        return send(packet);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    send_ack(STATUS, plen=6)
 | 
			
		||||
    prints(win, "status done")
 | 
			
		||||
    private byte[] wait_ack() throws IOException, TimeoutException {
 | 
			
		||||
        byte[] buffer = new byte[mExpectLen];
 | 
			
		||||
        int bytes;
 | 
			
		||||
 | 
			
		||||
    send_ack(PING)
 | 
			
		||||
    prints(win, "ping done")
 | 
			
		||||
        long now = System.currentTimeMillis();
 | 
			
		||||
 | 
			
		||||
    send_ack(INIT_A3)
 | 
			
		||||
    prints(win, "A3 done")
 | 
			
		||||
        if ((now - mTimesent) > 1000000) {
 | 
			
		||||
            mWaitAck = false;
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    send_ack(INIT_A4)
 | 
			
		||||
    prints(win, "A4 done")
 | 
			
		||||
        if (mInputStream.available() < mExpectLen)
 | 
			
		||||
            return null;
 | 
			
		||||
 | 
			
		||||
    send_ack(START)
 | 
			
		||||
    prints(win, "START done")
 | 
			
		||||
        bytes = mInputStream.read(buffer);
 | 
			
		||||
 | 
			
		||||
    level = 1
 | 
			
		||||
        if (null != mDebugListener)
 | 
			
		||||
            mDebugListener.onRead(Arrays.copyOfRange(buffer, 0, bytes));
 | 
			
		||||
 | 
			
		||||
    while True:
 | 
			
		||||
        sleep(0.25)
 | 
			
		||||
        while True:
 | 
			
		||||
            key = win.getch()
 | 
			
		||||
            if key == ord('q'):
 | 
			
		||||
                return
 | 
			
		||||
            elif key == ord('a') or key == curses.KEY_UP or key == curses.KEY_RIGHT:
 | 
			
		||||
                if level < 31:
 | 
			
		||||
                    level += 1
 | 
			
		||||
                prints(win, "Level: %d" % level)
 | 
			
		||||
                send_level(level)
 | 
			
		||||
        if (bytes != mExpectLen) {
 | 
			
		||||
            throw new IOException("Wrong number of bytes read. Expected " + mExpectLen + ", got " + bytes);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            elif key == ord('y') or key == curses.KEY_DOWN or key == curses.KEY_LEFT:
 | 
			
		||||
                if level > 1:
 | 
			
		||||
                    level -= 1
 | 
			
		||||
                prints(win, "Level: %d" % level)
 | 
			
		||||
                send_level(level)
 | 
			
		||||
            elif key == -1:
 | 
			
		||||
                break
 | 
			
		||||
        if (buffer[0] != mExpectPacket[0]) {
 | 
			
		||||
            throw new IOException("Byte 0 wrong. Expected " + String.format("%02x", mExpectPacket[0]) + ", got " + String.format("%02x", buffer[0]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        got = send_ack(READ, plen=21)
 | 
			
		||||
        if len(got) == 21:
 | 
			
		||||
            ic = IConsole(got)
 | 
			
		||||
            power_meter.update(power = ic.power, cadence = ic.rpm)
 | 
			
		||||
            speed.update(ic.speed)
 | 
			
		||||
            win.addstr(0,0, "%s - %s - %s - %s - %s - %s - %s - %s" % (ic.time_str,
 | 
			
		||||
                                                             ic.speed_str,
 | 
			
		||||
                                                             ic.rpm_str,
 | 
			
		||||
                                                             ic.distance_str,
 | 
			
		||||
                                                             ic.calories_str,
 | 
			
		||||
                                                             ic.hf_str,
 | 
			
		||||
                                                             ic.power_str,
 | 
			
		||||
                                                             ic.lvl_str))
 | 
			
		||||
        if (buffer[1] != mExpectPacket[1]) {
 | 
			
		||||
            throw new IOException("Byte 1 wrong. Expected " + String.format("%02x", mExpectPacket[1]) + ", got " + String.format("%02x", buffer[1]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
        return buffer;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
        send_ack(STOP)
 | 
			
		||||
        send_ack(PING)
 | 
			
		||||
    private boolean processIOSend() throws IOException {
 | 
			
		||||
        switch (mCurrentState) {
 | 
			
		||||
            case BEGIN:
 | 
			
		||||
                mCurrentState = mNextState;
 | 
			
		||||
                break;
 | 
			
		||||
            case PING:
 | 
			
		||||
                send(PING);
 | 
			
		||||
                break;
 | 
			
		||||
            case A0:
 | 
			
		||||
                send(INIT_A0, (byte)0xb7, 6);
 | 
			
		||||
                break;
 | 
			
		||||
            case A1:
 | 
			
		||||
                send(STATUS, 6);
 | 
			
		||||
                break;
 | 
			
		||||
            case A1_POST_PING:
 | 
			
		||||
                send(PING);
 | 
			
		||||
                break;
 | 
			
		||||
            case A3:
 | 
			
		||||
                send(INIT_A3);
 | 
			
		||||
                break;
 | 
			
		||||
            case A4:
 | 
			
		||||
                send(INIT_A4);
 | 
			
		||||
                break;
 | 
			
		||||
            case START:
 | 
			
		||||
                send(START);
 | 
			
		||||
                break;
 | 
			
		||||
            case STOP:
 | 
			
		||||
                send(STOP);
 | 
			
		||||
                break;
 | 
			
		||||
            case READ:
 | 
			
		||||
                send(READ);
 | 
			
		||||
                break;
 | 
			
		||||
            case SETLEVEL:
 | 
			
		||||
                send_level(mSetLevel);
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 */
 | 
			
		||||
    private boolean processIOAck() throws IOException, TimeoutException {
 | 
			
		||||
        byte[] got = null;
 | 
			
		||||
        got = wait_ack();
 | 
			
		||||
        if (null == got)
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        if(mCurrentState == State.READ)
 | 
			
		||||
            mDataListener.onData(new Data(got));
 | 
			
		||||
 | 
			
		||||
        mCurrentState = mNextState;
 | 
			
		||||
        switch (mNextState) {
 | 
			
		||||
            case BEGIN:
 | 
			
		||||
                mNextState = State.PING;
 | 
			
		||||
                break;
 | 
			
		||||
            case PING:
 | 
			
		||||
                mNextState = State.PING;
 | 
			
		||||
                break;
 | 
			
		||||
            case A0:
 | 
			
		||||
                mNextState = State.A1;
 | 
			
		||||
                break;
 | 
			
		||||
            case A1:
 | 
			
		||||
                mNextState = State.A1_POST_PING;
 | 
			
		||||
                break;
 | 
			
		||||
            case A1_POST_PING:
 | 
			
		||||
                mNextState = State.A3;
 | 
			
		||||
                break;
 | 
			
		||||
            case A3:
 | 
			
		||||
                mNextState = State.A4;
 | 
			
		||||
                break;
 | 
			
		||||
            case A4:
 | 
			
		||||
                mNextState = State.START;
 | 
			
		||||
                break;
 | 
			
		||||
            case START:
 | 
			
		||||
                mNextState = State.READ;
 | 
			
		||||
                break;
 | 
			
		||||
            case STOP:
 | 
			
		||||
                mNextState = State.PING;
 | 
			
		||||
                break;
 | 
			
		||||
            case READ:
 | 
			
		||||
                mNextState = State.READ;
 | 
			
		||||
                break;
 | 
			
		||||
            case SETLEVEL:
 | 
			
		||||
                mNextState = State.READ;
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    boolean processIO() {
 | 
			
		||||
        synchronized (this) {
 | 
			
		||||
            try {
 | 
			
		||||
                if (! mWaitAck) {
 | 
			
		||||
                    return processIOSend();
 | 
			
		||||
                } else {
 | 
			
		||||
                    return processIOAck();
 | 
			
		||||
                }
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                mDataListener.onError(e);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static byte[] hexStringToByteArray(String s) {
 | 
			
		||||
        int len = s.length();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,18 +32,21 @@
 | 
			
		|||
        android:layout_height="wrap_content"
 | 
			
		||||
        android:orientation="horizontal" >
 | 
			
		||||
 | 
			
		||||
        <EditText
 | 
			
		||||
            android:id="@+id/edit_text_out"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:layout_gravity="bottom"
 | 
			
		||||
            android:layout_weight="1" />
 | 
			
		||||
 | 
			
		||||
        <Button
 | 
			
		||||
            android:id="@+id/button_send"
 | 
			
		||||
            android:id="@+id/button_start"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:text="@string/send" />
 | 
			
		||||
            android:text="@string/start" />
 | 
			
		||||
        <Button
 | 
			
		||||
            android:id="@+id/button_stop"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:text="@string/stop" />
 | 
			
		||||
        <Button
 | 
			
		||||
            android:id="@+id/button_disconnect"
 | 
			
		||||
            android:layout_width="wrap_content"
 | 
			
		||||
            android:layout_height="wrap_content"
 | 
			
		||||
            android:text="@string/disconnect" />
 | 
			
		||||
    </LinearLayout>
 | 
			
		||||
 | 
			
		||||
</LinearLayout>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,6 @@
 | 
			
		|||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 | 
			
		||||
 | 
			
		||||
    <!--  BluetoothChat -->
 | 
			
		||||
    <string name="send">Send</string>
 | 
			
		||||
    <string name="not_connected">You are not connected to a device</string>
 | 
			
		||||
    <string name="bt_not_enabled_leaving">Bluetooth was not enabled. Leaving Bluetooth Chat.</string>
 | 
			
		||||
    <string name="title_connecting">connecting...</string>
 | 
			
		||||
| 
						 | 
				
			
			@ -37,5 +36,8 @@
 | 
			
		|||
    <string name="secure_connect">Connect a device - Secure</string>
 | 
			
		||||
    <string name="insecure_connect">Connect a device - Insecure</string>
 | 
			
		||||
    <string name="discoverable">Make discoverable</string>
 | 
			
		||||
    <string name="start">Start</string>
 | 
			
		||||
    <string name="stop">Stop</string>
 | 
			
		||||
    <string name="disconnect">Disconnect</string>
 | 
			
		||||
 | 
			
		||||
</resources>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue