Vamos a programar #29 - Inútil Apps #2 - Creando un socket bluetooth (arduino y android)

Hola a todos, el día de hoy vamos a continuar con Clock View. Ahora con todo el hardware listo y con la parte de software de arduino también listo, solo queda crear una forma de interactuar con el hardware de Clock View. Al carecer de botones solo nos queda la opción de usar el modulo Bluetooth, para comunicarnos por medio de este, podemos usar aplicaciones que ya estan disponibles en la Playstore (S2 Terminal for bluetooth por ejemplo), pero esa no es la idea del blog, en la mediada de lo posible trataremos de usar nuestro propio software para hacer las cosas.

El dia de hoy les quiero presentar Clock View para android, una aplicación que tiene cómo unica función; conectar con el modulo bluetooth HC-05 o HC-06 y cambiar los ajustes de Clock View.

La aplicacion dispone de 6 botones y una barra de "seek". Para usarla, primero debes de asegurarte de que todo el hardware está listo, despues debes de iniciar la conexion con el boton "Conectar con clock view", cuando aparace un mensaje diciendo que la conexion se llevo a cabo, puedes modificar los ajustes.


Hoy solo veremos el código, en el siguiente post, explicaré un poco acerca de cómo se realiza el intercambio de datos entre arduino y android.

El código.

El siguiente es el código en java que se encarga de hacer funcionar las cosas, los estilos y demás "layouts", irán en la descarga completa al final del post.

package com.mdev.clockview;

import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.Calendar;

import static com.mdev.clockview.R.layout.paired_devices_list;

public class MainActivity extends Activity {

	BluetoothAdapter myBluetoothAdapter = null;
	Button BtnConnect, BtnOnOff, BtnSecondsShow, BtnSyncHour, BtnChangeFormat,BtnDisconnect;
	SeekBar SkBright;
	TextView TxtArduinoRec, TxtBrigthValue;

	String address = null;
	private ProgressDialog progress;
	BluetoothSocket btSocket = null;
	private boolean isBtConnected = false;
	private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
	final int RECEIVE_MESSAGE = 1;
	private StringBuilder sb = new StringBuilder();
	private ConnectedThread mConnectedThread;
	Handler h;

	private Set<BluetoothDevice> pairedDevices;
	ListView myListView;
	ArrayAdapter BTArrayAdapter;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
		setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
		BtnConnect = (Button)findViewById(R.id.BtnConnect);
		myListView = (ListView)findViewById(R.id.BTList);
		TxtArduinoRec = (TextView)findViewById(R.id.TxtArduinoReturn);
		BtnOnOff = (Button)findViewById(R.id.BtnOn);
		BtnSecondsShow = (Button)findViewById(R.id.BtnShowS);
		BtnSyncHour = (Button)findViewById(R.id.BtnSync);
		BtnChangeFormat = (Button)findViewById(R.id.BtnFormat);
		BtnDisconnect = (Button)findViewById(R.id.BtnDisconnect);
		SkBright = (SeekBar)findViewById(R.id.SKBrillo);
		TxtBrigthValue = (TextView)findViewById(R.id.txtSeekValue);

		myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

		if (myBluetoothAdapter == null) {
			msg("El bluetooth no es soportado por este dispositivo");
		}
		else {
			msg("Esperando la conexion");
		}
		SkBright.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

			@Override
			public void onProgressChanged(SeekBar seekBar, int progress,
										  boolean fromUser) {
				TxtBrigthValue.setText(String.valueOf(progress));
				if (isBtConnected)
				{
					String result = String.format(">SETB%1$02d", progress);
					mConnectedThread.write(result);
				}
			}

			@Override
			public void onStartTrackingTouch(SeekBar seekBar) {
			}

			@Override
			public void onStopTrackingTouch(SeekBar seekBar) {

			}
		});
		BtnConnect.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View view) {
				if (!myBluetoothAdapter.isEnabled()) {
					Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
					startActivityForResult(turnOnIntent, 1);
				}else{
					showBTDialog();
				}
			}
		});
		BtnOnOff.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">SCRA");
				}
			}
		});

		BtnSecondsShow.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">DISS");
				}
			}
		});

		BtnSyncHour.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(BuildHourToArduino());
				}
			}
		});

		BtnChangeFormat.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					mConnectedThread.write(">SETF");
				}
			}
		});
		
		BtnDisconnect.setOnClickListener(new View.OnClickListener()
		{
			@Override
			public void onClick(View view){
				if (isBtConnected)
				{
					Disconnect();
				}
			}
		});
		//encargado de procesar los mensajes.
		h = new Handler() {
			public void handleMessage(android.os.Message msg) {
				switch (msg.what)
				{
					case RECEIVE_MESSAGE:
						byte[] readBuf = (byte[]) msg.obj;
						String strIncom = new String(readBuf, 0, msg.arg1);
						sb.append(strIncom);
						int endOfLineIndex = sb.indexOf("\r\n");
						if (endOfLineIndex > 0)
						{
							String sbprint = sb.substring(0, endOfLineIndex);
							sb.delete(0, sb.length());
							TxtArduinoRec.setText("Data from Arduino: " + sbprint);
						}
						break;
				}
			};
		};

	}
	private void msg(String s)
	{
		Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
	}
	private String BuildHourToArduino(){
		//>SETH2016122119001004
		//>SETHAAAAMMDDHHMMSSWW
		Calendar c = Calendar.getInstance();
		int DiaSemana = c.get(Calendar.DAY_OF_WEEK);
		int Anio = c.get(Calendar.YEAR);
		int Mes = c.get(Calendar.MONTH);
		int Dia = c.get(Calendar.DAY_OF_MONTH);
		int Horas = c.get(Calendar.HOUR_OF_DAY);
		int Minutos = c.get(Calendar.MINUTE);
		int Segundos = c.get(Calendar.SECOND);

		String DateForArduino = String.format(">SETH%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d",
				Anio, Mes + 1, Dia, Horas, Minutos,Segundos, DiaSemana);
		msg(DateForArduino);

		return DateForArduino;
	}

	private void Disconnect()
	{
		if (btSocket!=null)
		{
			try
			{
				btSocket.close();
				isBtConnected = false;
			}
			catch (IOException e)
			{ msg("Error");}
		}
	}

	private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
	{
		public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3) {
			if (myBluetoothAdapter.isEnabled()) {
				String info = ((TextView) v).getText().toString();
				address = info.substring(info.length() - 17);
				msg(address);

			} else {
				msg("El Bluetooth debe de estar encendido.");
			}
		}
	};


	public void showBTDialog() {
		final AlertDialog.Builder popDialog = new AlertDialog.Builder(this);
		final LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
		final View Viewlayout = inflater.inflate(paired_devices_list, (ViewGroup) findViewById(R.id.bt_list));

		popDialog.setTitle("Dispositivos Bluetooth:");
		popDialog.setView(Viewlayout);

		myListView = (ListView) Viewlayout.findViewById(R.id.BTList);
		BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
		myListView.setAdapter(BTArrayAdapter);
		pairedDevices = myBluetoothAdapter.getBondedDevices();

		for(BluetoothDevice device : pairedDevices)
			BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());

		myListView.setOnItemClickListener(myListClickListener);
		// Button OK
		popDialog.setPositiveButton("Conectar",
				new DialogInterface.OnClickListener() {
					public void onClick(DialogInterface dialog, int which) {
						if (address != null)
						{
							new ConnectBT().execute();
						}
						dialog.dismiss();
					}
				});
		popDialog.create();
		popDialog.show();

	}
	private class ConnectedThread extends Thread {
		private final InputStream mmInStream;
		private final OutputStream mmOutStream;

		public ConnectedThread(BluetoothSocket socket) {
			InputStream tmpIn = null;
			OutputStream tmpOut = null;
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) { }

			mmInStream = tmpIn;
			mmOutStream = tmpOut;
		}

		public void run() {
			byte[] buffer = new byte[256];
			int bytes;
			while (true) {
				try {
					bytes = mmInStream.read(buffer);
					h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();
				} catch (IOException e) {
					break;
				}
			}
		}

		public void write(String message) {
			byte[] msgBuffer = message.getBytes();
			try {
				mmOutStream.write(msgBuffer);
			} catch (IOException e) {
				msg("Error al enviar: " + e.getMessage());

			}
		}
	}



	private class ConnectBT extends AsyncTask<Void, Void, Void>
	{
		private boolean ConnectSuccess = true;

		@Override
		protected void onPreExecute()
		{
			progress = ProgressDialog.show(MainActivity.this, "Conectando...", "Espera...!!!");
		}

		@Override
		protected Void doInBackground(Void... devices)
		{
			try
			{
				if (btSocket == null || !isBtConnected)
				{
					myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
					BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
					BluetoothDevice dispositivo = myBluetoothAdapter.getRemoteDevice(address);
					btSocket = createBluetoothSocket(dispositivo);
					btSocket.connect();
				}
			}
			catch (IOException e)
			{
				ConnectSuccess = false;
			}
			return null;
		}

		private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
			if(Build.VERSION.SDK_INT >= 10){
				try {
					final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
					return (BluetoothSocket) m.invoke(device, myUUID);
				} catch (Exception e) {
					msg("No se pudo crear la conexion");
				}
			}
			return  device.createRfcommSocketToServiceRecord(myUUID);
		}

		@Override
		protected void onPostExecute(Void result)
		{
			super.onPostExecute(result);

			if (!ConnectSuccess)
			{
				msg("La conexion falló, intentelo de nuevo");
				isBtConnected = false;
			}
			else
			{
				msg("Conectado.");
				isBtConnected = true;
				mConnectedThread = new ConnectedThread(btSocket);
				mConnectedThread.start();
			}
			progress.dismiss();
		}
	}
}

Cómo todo el código requiere una explicacion detallada (o si no quieres meterte en programacion), por ahora solo dejo el APK ya compilado,
Los leo luego.

No hay comentarios.