"¿Qué puertos deportivos?" o controlamos el controlador a través de bluetooth usando una aplicación móvil en Xamarin (Android)

En un artículo anterior , prometí hablar sobre cómo conectar CANNY 3 tiny usando UART a bluetooth. Y dado que realmente no da un paseo en estas vacaciones de mayo, se decidió pasar tiempo con beneficio y aún así cumplir la promesa. Pero solo para conectar el controlador al adaptador Bluetooth HC-06, sería demasiado fácil para Habr.

Por lo tanto, no solo conectaremos todo, sino que también escribiremos una aplicación de Android primitiva para nuestro circuito usando C # y Xamarin.

Si le gusta monitorear los "interruptores de límite" y los interruptores de láminas, como me encanta, usted es bienvenido bajo cat.



Esto es de lo que hablaremos hoy:

Parte I: Introducción
Parte II: Conexión del circuito y programa para CANNY 3 Tiny
Parte III: Escribimos una aplicación en Xamarin para Android
Parte IV: Conclusión

Parte I: Introducción


Comenzaré con el bueno, excepto por las inserciones del código del programa en C #, luego esta vez el artículo será relativamente pequeño, porque examinamos las técnicas básicas de trabajar con el controlador anteriormente. Para no repetir una vez más, aquí hay una lista de artículos en los que ya hemos examinado los métodos básicos para trabajar con el controlador CANNY:

  1. "Uno, dos, tres - ¡quema el árbol de Navidad!" o mi primer vistazo al pequeño controlador CANNY 3 : en este artículo analizamos qué es el controlador, así como los conceptos básicos para trabajar en el entorno de desarrollo CannyLab.
  2. "El Destino tiene muchas formas ..." o automatizamos el control de una lámpara usando CANNY 3 Tiny y un fotorresistor . En este artículo analizamos cómo trabajar con un puerto COM virtual USB, conectar sensores al ADC, así como PWM de alta frecuencia en las salidas del controlador.
  3. « ...» (CANNY Arduino) Raspberry PI — UART, .

Al preparar este artículo, utilicé el siguiente hardware: controlador pequeño CANNY 3, adaptador Bluetooth HC-06, interruptor de límite (módulo Trema), interruptor de láminas, auriculares con cable viejos, placa de pruebas, cables, cocodrilos.

Construiremos un sistema que, utilizando una aplicación móvil, monitoree el estado de dos sensores y, si es necesario, puede hacer sonar manualmente una alarma.

Todo lo que se presentará en este artículo se inventa únicamente con fines educativos y de demostración. Solo quería mostrar algunos trucos para trabajar con el controlador, así como para las piezas de hierro compradas de una sola vez para de alguna manera resolver su valor.

A pesar de la naturaleza del problema que se está resolviendo, que está lejos de la realidad, imaginaremos que estamos haciendo un sistema de monitoreo detrás de la puerta corredera del compartimento. Cuando comience a moverse, el interruptor de láminas funcionará, y al final del camino dará una señal al remolque. Si necesitamos llamar la atención, por ejemplo, para que la puerta esté cerrada, daremos una señal "chirriante" a través del altavoz. Es cierto, no tengo un altavoz, pero hay auriculares viejos.



Bueno y, como siempre, una nota. No recomiendo utilizar los materiales de este artículo como la verdad definitiva. Hice muchas cosas por primera vez, ciertamente se pueden hacer mejor.


Parte II: Conexión del circuito y programa para CANNY 3 tiny


Para comenzar, para no ofender a nadie en derechos de autor, tomé prestado del foro , pero los adapté a tu tarea.

El diagrama de conexión es el siguiente: el



interruptor de límite y el interruptor de láminas están conectados a los terminales del controlador No. 6 y No. 5, los auriculares al terminal No. 4 (tiene un RF PWM), UART RX es el terminal No. 1, UART TX es el terminal No. 2, terminal No. 3 Se utiliza para suministrar "+ 5V", la salida "-" - para la comunicación con la "tierra".

Así es como se ve en el ensamblaje:



Desarrollé el diagrama (programa) para CANNY 3 tiny en CannyLab versión 1.42, tal vez en otras versiones del entorno de desarrollo y con otros controladores, será necesario realizar cambios en el diagrama.

Esto es lo que sucedió: los



bloques asociados con la configuración del controlador y el envío de mensajes a través de UART se desmontaron en un artículo anterior .

Examinemos con más detalle los dos restantes.

El bloque " Recibir mensaje UART " es responsable de encender la sirena (auriculares). En principio, es necesario analizar un ejemplo de recepción de un mensaje a través de UART.

Primero, verificamos si los datos recibidos están en el UART, si es así, luego enviamos uno a la entrada del disparador D "E", en cuyo caso el disparador copia el valor de la entrada "D" en la que escribiremos los dos primeros caracteres del mensaje recibido a través del UART. No quería complicarlo todo, así que seguiremos usando un esquema simple. Asumimos que UART nos llegará a cualquier número del 00 al 99, traduciremos este número de una forma simbólica a una numérica (recomiendo leer cómo funciona el bloque convertidor , tenía un pequeño "enchufe" con él). Además, cualquier valor "> 0" en la entrada del detector de borde de ataque produce una sola señal, que enciende la salida 5 durante 5 segundos, operando en el modo RF PWM.

Puede jugar en la configuración con el período de llenado del RF PWM, el sonido en los auriculares dependerá de esto.

Pasemos al bloque"Formación del mensaje" . Su implementación a primera vista puede parecer inusual. Esto se explica por el hecho de que realmente no descubrí cómo trabajar con el programa de terminal Bluetooth serie y con el mismo protocolo bluetooth en Xamarin.

Me adelantaré un poco y diré que no he aprendido cómo recibir mensajes enviados desde el controlador en mi teléfono inteligente. Si todo fue obvio con el UART con cable en el último artículo, entonces con Bluetooth, en la práctica, en lugar del mensaje enviado, solo se puede leer su parte y se viola el significado del comando transmitido.

Decidí que la solución más simple es transmitir un solo número, que está garantizado para llegar al destinatario sin pérdida.

En nuestro caso, monitoreamos el estado discreto del interruptor de láminas y el interruptor de límite. Es decir, solo tenemos 4 combinaciones posibles: el interruptor de láminas y el interruptor de límite están apagados, solo uno está encendido, ambos están encendidos.

Dado que el interruptor de láminas y el interruptor de límite dan una señal discreta (0/1), debe distinguirlos de alguna manera. Para hacer esto, multiplicamos el valor de la señal de lámina por 2. Ahora resulta que la suma de las señales nos dará valores de 0 a 3.

Ahora analizaremos una opción no obvia con cincuenta añadidos a este valor. El hecho es que CannyLab transfiere un par de caracteres a UART, es decir, en lugar de 3, digamos 03, pero como dije, existe el riesgo de perder parte de la información. Por ejemplo, a partir del valor 01, el programa en el teléfono inteligente puede leer solo el primer "0", y esto ya será un error.

Sería posible confundirse y transformar los datos, reemplazando, por ejemplo, el carácter "D1" del registro con alguna letra o espacio, pero decidí hacerlo más fácil. Convertí el valor 01 a 51 (02 a 52, etc.). Los cinco no llevan señal y la corté a nivel de programa para un teléfono inteligente. Por lo tanto, siempre garantizamos que la parte útil del mensaje permanezca.

Cargamos el programa en el controlador, hacemos clic en "ejecutar", si todo funciona según lo planeado, entonces el HC-06 parpadeará periódicamente con un LED rojo.

A continuación, emparejamos el teléfono inteligente con el adaptador. Ahora puede comprobar el rendimiento en la aplicación "Terminal Bluetooth serie" o cualquier otra con una funcionalidad similar.

Escriba la dirección del adaptador Bluetooth, nos será útil en el próximo capítulo.



Como puede ver, los datos provienen, dependiendo del estado de los sensores, y si envía "11", se escucha un desagradable chirrido en los auriculares. Podríamos detenernos aquí, pero bosquejemos una aplicación primitiva.

El programa para el controlador y el código fuente del programa para el teléfono inteligente se pueden descargar desde GitHub.

Me gustaría señalar que no tiene que implementar todo en el hardware específicamente en los controladores CANNY, puede escribir un programa para Arduino u otro controlador que desee. Inicialmente, yo también planeé escribir una versión adicional del boceto para Arduino, pero como maté a casi todas las vacaciones de mayo, simplemente ya no tuve la fuerza para conectar CANNY y la aplicación para teléfonos inteligentes.

Parte III: Escribir una aplicación de Android Xamarin


Sé que Xamarin, por decirlo suavemente, no es la solución más popular para el desarrollo móvil. Y tal vez ya tengas una pregunta: "¿Por qué la elegí?" . Me gustaría responderle con palabras de la canción del mismo nombre de Psoya Korolenko:



Sinceramente, no hay razones objetivas. Hace solo un par de años aprendí los conceptos básicos de C # y todos querían ver qué es Xamarin. Y ahora, debido al "autoaislamiento", las manos finalmente han llegado.

Bueno, déjame recordarte de nuevo. Esta es la primera vez que conozco a Xamarin y esta es mi primera aplicación de Android. No copie ciegamente mi código de curva, si de repente puede encontrar una solución más hermosa, úsela.

Al desarrollar mi programa, confié en este material. El artículo no está especialmente masticado, e incluso en español, por lo que aún me parece apropiado compartir con ustedes mi variación sobre este tema.

Creé el programa en la edición comunitaria Visual Studio 2019.

En primer lugar, cree un nuevo proyecto de Android vacío (Xamarin), como en la imagen.



Realicé cambios solo en tres archivos, se pueden ver completamente en GitHub , y aquí analizaremos solo las partes importantes: los permisos de

AndroidManifest.xml

2 se agregan a la plantilla estándar:

  <uses-permission android:name="android.permission.BLUETOOTH"/>
  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

activity_main.xml El
contenedor predeterminado (RelativeLayout) se ha eliminado. En cambio, el contenedor LinearLayout se agregó simplemente porque es más simple. En este contenedor, todos los elementos están alineados verticalmente, extendiéndose a lo largo de todo el ancho de la pantalla.

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:minWidth="25px"
    android:minHeight="25px"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/linearLayout1">
    <TextView
        android:text="Reed switch status - undefined"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/rSwitch"
        android:textSize="12pt" />
    <TextView
        android:text="End sensor status - undefined"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/EndSensor"
        android:textSize="12pt" />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/startSiren"
        android:text="Send signal to siren" />
    <Switch
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/bltSwitch"
        android:checked="false"
        android:showText="true"
        android:text="Connect bluetooth" />
    <TextView
        android:text="status"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/status" />
</LinearLayout>

Cualquiera que esté un poco familiarizado con el diseño HTML o XML puede comprender fácilmente la estructura de la interfaz de usuario. Tenemos tres campos de texto de solo lectura (TextView), un interruptor (Switch), que básicamente funciona como una casilla de verificación y un botón ordinario (Button). Los elementos se pueden colocar en el formulario arrastrándolos y soltándolos desde el constructor, y en la ventana de propiedades o en el código para configurarlos más convenientemente como Id, stubs de texto y otros parámetros.

Queda por describir la lógica del programa.

MainActivity.cs

A continuación, debajo del spoiler, todo el código es para conveniencia

Código completo de MainActivity.cs
// based on http://alejandroruizvarela.blogspot.com/2014/01/bluetooth-arduino-xamarinandroid.html
// for this article https://habr.com/ru/post/500454/


// based on http://alejandroruizvarela.blogspot.com/2014/01/bluetooth-arduino-xamarinandroid.html
// for this article https://habr.com/ru/post/500454/


using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using System.Linq;
using System;
using System.IO;
using Java.Util;
using Android.Bluetooth;
using System.Threading.Tasks;

namespace _6.Canny_Xanarin_Bluetooth_Android
{
    [Activity(Label = "Control Canny 3 tiny via bluetooth", Theme = "@style/AppTheme", MainLauncher = true)]
    public class MainActivity : AppCompatActivity
    {

        Button startSiren;
        TextView rSwitch;
        TextView EndSensor;
        Switch bltSwitch;
        TextView status;
        private Java.Lang.String dataToSend;
        private BluetoothAdapter mBluetoothAdapter = null;
        private BluetoothSocket btSocket = null;
        private Stream outStream = null;
        // don't forget change addres to your device:
        private static string address = "98:D3:91:F9:6C:F6";
        // MY_UUID can be saved as is
        private static UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
        private Stream inStream = null;


        protected override void OnCreate(Bundle savedInstanceState)
        {

            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            startSiren = FindViewById<Button>(Resource.Id.startSiren);
            rSwitch = FindViewById<TextView>(Resource.Id.rSwitch);
            EndSensor = FindViewById<TextView>(Resource.Id.EndSensor);
            status = FindViewById<TextView>(Resource.Id.status);
            bltSwitch = FindViewById<Switch>(Resource.Id.bltSwitch);


            startSiren.Click += startSiren_ClickOnButtonClicked;
            bltSwitch.CheckedChange += bltSwitch_HandleCheckedChange;
            CheckBt();
        }

        private void CheckBt()
        {
            mBluetoothAdapter = BluetoothAdapter.DefaultAdapter;

            if (!mBluetoothAdapter.Enable())
            {
                Toast.MakeText(this, "Bluetooth Off",
                    ToastLength.Short).Show();
            }

            if (mBluetoothAdapter == null)
            {
                Toast.MakeText(this,
                    "Bluetooth does not exist or is busy", ToastLength.Short)
                    .Show();
            }
        }

        void startSiren_ClickOnButtonClicked(object sender, EventArgs e)
        {
            if (bltSwitch.Checked)
            {
                try
                {
                    dataToSend = new Java.Lang.String("11");
                    writeData(dataToSend);
                    System.Console.WriteLine("Send signal to siren");
                }
                catch (System.Exception execept)
                {
                    System.Console.WriteLine("Error when send data" + execept.Message);
                }

            }
            else status.Text = "bluetooth not connected";
        }
        void bltSwitch_HandleCheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e)
        {
            if (e.IsChecked)
            {
                Connect();
            }
            else
            {
                status.Text = "bluetooth not connected";
                if (btSocket.IsConnected)
                {
                    try
                    {
                        btSocket.Close();
                        System.Console.WriteLine("Connection closed");
                    }
                    catch (System.Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }

        public void Connect()
        {
            BluetoothDevice device = mBluetoothAdapter.GetRemoteDevice(address);
            System.Console.WriteLine("Connection in progress" + device);
            mBluetoothAdapter.CancelDiscovery();
            try
            {
                btSocket = device.CreateRfcommSocketToServiceRecord(MY_UUID);
                btSocket.Connect();
                System.Console.WriteLine("Correct Connection");
                status.Text = "Correct Connection to bluetooth";
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                try
                {
                    btSocket.Close();
                    System.Console.WriteLine("Connection closed");
                }
                catch (System.Exception)
                {
                    System.Console.WriteLine("Impossible to connect");
                    status.Text = "Impossible to connect";
                }
                System.Console.WriteLine("Socket Created");
  
            }
            beginListenForData();

        }

        public void beginListenForData()
        {
            try
            {
                inStream = btSocket.InputStream;
            }
            catch (System.IO.IOException ex)
            {
                Console.WriteLine(ex.Message);
            }
            Task.Factory.StartNew(() => {
                byte[] buffer = new byte[1024];
                int bytes;
                
                while (true)
                {

                    try
                    {
                        bytes = inStream.Read(buffer, 0, 1024);
                        System.Console.WriteLine("bytes " + bytes.ToString());
                        if (bytes > 0)
                        {
                            
                            RunOnUiThread(() => {
                                string valor = System.Text.Encoding.ASCII.GetString(buffer).Replace("5",String.Empty);
                                // transform string for deleate all symbols except 1-4(command from canny).
                                string command = new string(valor.Where(char.IsDigit).ToArray());

                                if (command.Length > 0)
                                {
                                     status.Text="data successfully readed";
                                    System.Console.WriteLine("command  " + command);
                                    switch (Int32.Parse(command))
                                    {
                                        case 0:
                                            rSwitch.Text = "reed switch - disconnected ";
                                            EndSensor.Text = "end sensor - not pressed ";
                                            break;
                                        case 1:
                                            rSwitch.Text = "reed switch - disconnected ";
                                            EndSensor.Text = "end sensor - pressed ";
                                            break;
                                        case 2:
                                            rSwitch.Text = "reed switch - connected ";
                                            EndSensor.Text = "end sensor - not pressed ";
                                            break;
                                        case 3:
                                            rSwitch.Text = "reed switch - connected ";
                                            EndSensor.Text = "end sensor - pressed ";
                                        break;
                                    }
                                }
                            });
                        }
                    }
                    catch (Java.IO.IOException)
                    {
                        RunOnUiThread(() => {
                            EndSensor.Text = "End sensor status - undefined";
                            rSwitch.Text = "Reed switch status - undefined ";
                        });
                        break;
                    }
                }
            });
        }

        private void writeData(Java.Lang.String data)
        {
            try
            {
                outStream = btSocket.OutputStream;
            }
            catch (System.Exception e)
            {
                System.Console.WriteLine("Error with OutputStream when write to Serial port" + e.Message);
            }

            Java.Lang.String message = data;

            byte[] msgBuffer = message.GetBytes();

            try
            {
                outStream.Write(msgBuffer, 0, msgBuffer.Length);
                System.Console.WriteLine("Message sent");
            }
            catch (System.Exception e)
            {
                System.Console.WriteLine("Error with  when write message to Serial port" + e.Message);
                status.Text = "Error with  when write message to Serial port";
            }
        }


    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
 }


Ahora en partes.

Bloques con conexión de espacios de nombres, declaración de clase, etc. Extrañaré.


Creamos variables con las que luego vincularemos los elementos de la interfaz de usuario:

   Button startSiren;
   TextView rSwitch;
   TextView EndSensor;
   Switch bltSwitch;
   TextView status;

Luego viene el código del ejemplo en el que me basé. Variables (campos) necesarias para el funcionamiento de ciertos métodos.

  private Java.Lang.String dataToSend;
        private BluetoothAdapter mBluetoothAdapter = null;
        private BluetoothSocket btSocket = null;
        private Stream outStream = null;
        // don't forget change addres to your device:
        private static string address = "98:D3:91:F9:6C:F6";
        // MY_UUID can be saved as is
        private static UUID MY_UUID = UUID.FromString("00001101-0000-1000-8000-00805F9B34FB");
        private Stream inStream = null;

Es importante para nosotros llevar la dirección de su módulo HC-06 al campo de dirección.

Dado que esta es mi primera experiencia de desarrollo para teléfonos inteligentes, incluido el trabajo con Xamarin, decidí no complicar nada, por lo que la dirección del dispositivo, como en el ejemplo original, es fija. Si lo desea, puede ver este artículo , parece que se ha implementado una enumeración de dispositivos Bluetooth disponibles.

Siga adelante.


        protected override void OnCreate(Bundle savedInstanceState)
        {

            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.activity_main);

            startSiren = FindViewById<Button>(Resource.Id.startSiren);
            rSwitch = FindViewById<TextView>(Resource.Id.rSwitch);
            EndSensor = FindViewById<TextView>(Resource.Id.EndSensor);
            status = FindViewById<TextView>(Resource.Id.status);
            bltSwitch = FindViewById<Switch>(Resource.Id.bltSwitch);


            startSiren.Click += startSiren_ClickOnButtonClicked;
            bltSwitch.CheckedChange += bltSwitch_HandleCheckedChange;
            CheckBt();
        }

Este método se crea automáticamente, nuestra tarea es asociar objetos UI en él con los campos de la clase, y también adjuntar controladores para reacciones a eventos ( startSiren.Click bltSwitch.CheckedChange).

Comprobación de la conexión a través de Bluetooth:


        private void CheckBt()
        {
            mBluetoothAdapter = BluetoothAdapter.DefaultAdapter;

            if (!mBluetoothAdapter.Enable())
            {
                Toast.MakeText(this, "Bluetooth Off",
                    ToastLength.Short).Show();
            }

            if (mBluetoothAdapter == null)
            {
                Toast.MakeText(this,
                    "Bluetooth does not exist or is busy", ToastLength.Short)
                    .Show();
            }
        }

Enciende la sirena. Esencialmente solo enviando los caracteres "11" al controlador:


   void startSiren_ClickOnButtonClicked(object sender, EventArgs e)
        {
            if (bltSwitch.Checked)
            {
                try
                {
                    dataToSend = new Java.Lang.String("11");
                    writeData(dataToSend);
                    System.Console.WriteLine("Send signal to siren");
                }
                catch (System.Exception execept)
                {
                    System.Console.WriteLine("Error when send data" + execept.Message);
                }

            }
            else status.Text = "bluetooth not connected";
        }

Comprobación del estado del interruptor (si se desplaza hacia la derecha, significa que está encendido):

   void bltSwitch_HandleCheckedChange(object sender, CompoundButton.CheckedChangeEventArgs e)
        {
            if (e.IsChecked)
            {
                Connect();
            }
            else
            {
                if (btSocket.IsConnected)
                {
                    try
                    {
                        btSocket.Close();
                        System.Console.WriteLine("Connection closed");
                    }
                    catch (System.Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }

Cuando enciende, comenzamos la conexión con Bluetooth.

Implementando la conexión directamente:

   public void Connect()
        {
            BluetoothDevice device = mBluetoothAdapter.GetRemoteDevice(address);
            System.Console.WriteLine("Connection in progress" + device);
            mBluetoothAdapter.CancelDiscovery();
            try
            {
                btSocket = device.CreateRfcommSocketToServiceRecord(MY_UUID);
                btSocket.Connect();
                System.Console.WriteLine("Correct Connection");
                status.Text = "Correct Connection to bluetooth";
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                try
                {
                    btSocket.Close();
                    System.Console.WriteLine("Connection closed");
                }
                catch (System.Exception)
                {
                    System.Console.WriteLine("Impossible to connect");
                    status.Text = "Impossible to connect";
                }
                System.Console.WriteLine("Socket Created");
  
            }
            beginListenForData();

        }

Y aquí está uno de los métodos más importantes: leer directamente los datos:


    public void beginListenForData()
        {
            try
            {
                inStream = btSocket.InputStream;
            }
            catch (System.IO.IOException ex)
            {
                Console.WriteLine(ex.Message);
            }
            Task.Factory.StartNew(() => {
                byte[] buffer = new byte[1024];
                int bytes;
                
                while (true)
                {

                    try
                    {
                        bytes = inStream.Read(buffer, 0, 1024);
                        System.Console.WriteLine("bytes " + bytes.ToString());
                        if (bytes > 0)
                        {
                            
                            RunOnUiThread(() => {
                                string valor = System.Text.Encoding.ASCII.GetString(buffer).Replace("5",String.Empty);
                                // transform string for deleate all symbols except 1-4(command from canny).
                                string command = new string(valor.Where(char.IsDigit).ToArray());

                                if (command.Length > 0)
                                {
                                     status.Text="data successfully readed";
                                    System.Console.WriteLine("command  " + command);
                                    switch (Int32.Parse(command))
                                    {
                                        case 0:
                                            rSwitch.Text = "reed switch - disconnected ";
                                            EndSensor.Text = "end sensor - not pressed ";
                                            break;
                                        case 1:
                                            rSwitch.Text = "reed switch - disconnected ";
                                            EndSensor.Text = "end sensor - pressed ";
                                            break;
                                        case 2:
                                            rSwitch.Text = "reed switch - connected ";
                                            EndSensor.Text = "end sensor - not pressed ";
                                            break;
                                        case 3:
                                            rSwitch.Text = "reed switch - connected ";
                                            EndSensor.Text = "end sensor - pressed ";
                                        break;
                                    }
                                }
                            });
                        }
                    }
                    catch (Java.IO.IOException)
                    {
                        RunOnUiThread(() => {
                            EndSensor.Text = "End sensor status - undefined";
                            rSwitch.Text = "Reed switch status - undefined ";
                        });
                        break;
                    }
                }
            });
        }

Dejé muchos elementos del método como en el ejemplo, tal como lo entiendo, al principio se crea una conexión al flujo de datos, si hay algo en el búfer con los datos leídos, luego se lee en una variable valor. Además, como prometí, simplemente borramos el número "5".

A continuación, eliminamos todos los caracteres excepto los números del mensaje leído. string command = new string(valor.Where(char.IsDigit).ToArray());

Bueno, después de eso todo es simple, dependiendo de qué número nos haya llegado, mostramos este o aquel estado en la interfaz de usuario.

No cambié fundamentalmente estos dos métodos:

  private void writeData(Java.Lang.String data)
        {
            try
            {
                outStream = btSocket.OutputStream;
            }
            catch (System.Exception e)
            {
                System.Console.WriteLine("Error with OutputStream when write to Serial port" + e.Message);
            }

            Java.Lang.String message = data;

            byte[] msgBuffer = message.GetBytes();

            try
            {
                outStream.Write(msgBuffer, 0, msgBuffer.Length);
                System.Console.WriteLine("Message sent");
            }
            catch (System.Exception e)
            {
                System.Console.WriteLine("Error with  when write message to Serial port" + e.Message);
                status.Text = "Error with  when write message to Serial port";
            }
        }


    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

            base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }
    }
 }

Según tengo entendido, este bloque de código implementa el envío de un mensaje y un controlador de eventos para superar el permiso de acceso a Bluetooth.

Bueno, eso es todo lo que queda para configurar una conexión de teléfono inteligente para depurar la aplicación .

Curiosamente, pero funciona:



Parte IV: Conclusión


Así es como funciona el programa en especie:



esa fue mi primera experiencia en el desarrollo de aplicaciones para un teléfono inteligente en Android.

Me gustaría señalar que VS 2019 y Xamarin en mi computadora vieja funcionan muy lentamente.

En la primera asamblea del proyecto, realmente pude comer estos suaves rollos franceses y beber té. Además, la aplicación en sí resultó ser francamente miserable, el interruptor de encendido / apagado no funciona muy convenientemente, pero por otro lado, dado que solo estoy un poco familiarizado con las técnicas básicas de desarrollo para .NET, así como el hecho de que no soy un programador, incluso podría sin pasar por un solo tutorial o una sola lección, describa su primera aplicación en un día. Por lo tanto, el umbral de entrada para crear una aplicación primaria es bastante bajo.

Según tengo entendido, los controladores CANNY se pueden usar al sintonizar automóviles, especialmente los domésticos, por lo que es bastante posible hacer algún tipo de "característica" y escribir una aplicación para un teléfono inteligente. Lo principal a recordar es que cuando se alimenta desde la red a bordo del vehículo, las salidas del controlador también tendrán el mismo voltaje que la entrada (por ejemplo, 12 V en lugar de 5 V). No olvide proteger el adaptador Bluetooth para que no falle sin darse cuenta.

El artículo resultó ser muy laborioso para mí, espero que no todo haya sido en vano y que te guste.

All Articles