"Welche Yachthäfen?" oder wir steuern den Controller über Bluetooth mit einer mobilen Anwendung auf Xamarin (Android)

In einem früheren Artikel habe ich versprochen, darüber zu sprechen, wie CANNY 3 tiny mit UART mit Bluetooth verbunden werden kann. Und da Sie in diesen Maiferien nicht wirklich spazieren gehen, wurde beschlossen, Zeit mit Nutzen zu verbringen und das Versprechen trotzdem einzuhalten. Aber nur um den Controller mit dem Bluetooth-Adapter HC-06 zu verbinden, wäre es für Habr zu einfach.

Daher werden wir nicht nur alles verbinden, sondern auch eine primitive Android-Anwendung für unsere Schaltung mit C # und Xamarin schreiben.

Wenn Sie die „Endschalter“ und die Reedschalter überwachen möchten, wie ich es liebe, sind Sie unter Katze willkommen.



Hier ist, worüber wir heute sprechen werden:

Teil I: Einführung
Teil II: Verbinden der Schaltung und des Programms für CANNY 3 winzig
Teil III: Wir schreiben eine Anwendung auf Xamarin für Android
Teil IV: Fazit

Teil I: Einführung


Ich beginne mit dem Guten, abgesehen von den Einfügungen des Programmcodes in C #. Diesmal ist der Artikel relativ klein, da wir die grundlegenden Techniken für die Arbeit mit dem Controller früher untersucht haben. Um es nicht noch einmal zu wiederholen, finden Sie hier eine Liste von Artikeln, in denen wir bereits die grundlegenden Methoden für die Arbeit mit dem CANNY-Controller untersucht haben:

  1. "Eins, zwei, drei - verbrenne den Weihnachtsbaum!" oder mein erster Blick auf den winzigen CANNY 3-Controller - in diesem Artikel haben wir analysiert, was der Controller ist und welche Grundlagen für die Arbeit in der CannyLab-Entwicklungsumgebung gelten.
  2. "Das Ziel hat viele Erscheinungsformen ..." oder wir automatisieren die Steuerung einer Lampe mit CANNY 3 tiny und einem Fotowiderstand. In diesem Artikel haben wir uns mit der Arbeit mit dem virtuellen USB-COM-Port, dem Anschließen von Sensoren an den ADC sowie dem Hochfrequenz-PWM an den Controller-Ausgängen befasst.
  3. « ...» (CANNY Arduino) Raspberry PI — UART, .

Bei der Vorbereitung dieses Artikels habe ich die folgende Hardware verwendet: CANNY 3 winziger Controller, HC-06 Bluetooth-Adapter, Endschalter (Trema-Modul), Reed-Schalter, alte kabelgebundene Kopfhörer, Steckbrett, Kabel, Krokodile.

Wir werden ein System bauen, das mithilfe einer mobilen Anwendung den Status von zwei Sensoren überwacht und bei Bedarf manuell einen Alarm auslösen kann.

Alles, was in diesem Artikel vorgestellt wird, wurde ausschließlich zu Bildungs- und Demonstrationszwecken erfunden. Ich wollte nur einige Tricks der Arbeit mit dem Controller zeigen, sowie für die Eisenstücke, die auf einmal gekauft wurden, um irgendwie ihren Wert herauszufinden.

Trotz der Art des zu lösenden Problems, das weit von der Realität entfernt ist, werden wir uns vorstellen, dass wir ein Überwachungssystem hinter der Schiebetür des Abteils herstellen. Wenn es sich in Bewegung setzt, funktioniert der Reed-Schalter und am Ende des Pfades gibt er ein Signal an den Anhänger. Wenn wir zum Beispiel Aufmerksamkeit erregen müssen, damit die Tür wieder geschlossen wird, geben wir über den Lautsprecher ein "quietschendes" Signal. Ich habe zwar keinen Lautsprecher, aber es gibt alte Kopfhörer.



Nun und wie immer eine Notiz. Ich empfehle dringend, die Materialien in diesem Artikel nicht als ultimative Wahrheit zu verwenden. Ich habe viele Dinge zum ersten Mal selbst gemacht, sie können sicherlich besser gemacht werden.


Teil II: Anschließen der Schaltung und des Programms für CANNY 3 tiny


Um loszulegen, um niemanden im Urheberrecht zu verletzen, habe ich mir etwas aus dem Forum ausgeliehen , aber ich habe sie für die Idee angepasst, den Controller mit dem HC-06 zu verbinden, indem ich ihn über die Anwendung „Serielles Bluetooth-Terminal“ und einige Tricks bei der Entwicklung des Diagramms gesteuert habe deine Aufgabe.

Das Anschlussschema sieht wie folgt aus: Der



Endschalter und der Reedschalter sind an die Klemmen des Controllers Nr. 6 und Nr. 5 angeschlossen, die Kopfhörer an Klemme Nr. 4 (RF-PWM), UART RX an Klemme Nr. 1, UART TX an Klemme Nr. 2, Klemme Nr. 3 Es wird verwendet, um "+ 5V", den Ausgang "-" - für die Kommunikation mit der "Masse" zu liefern.

So sieht es in der Montage aus:



Ich habe das Diagramm (Programm) für CANNY 3 tiny in CannyLab Version 1.42 entwickelt, möglicherweise in anderen Versionen der Entwicklungsumgebung und mit anderen Controllern müssen Änderungen am Diagramm vorgenommen werden.

Folgendes ist passiert: Die



Blöcke, die mit dem Einrichten des Controllers und dem Senden von Nachrichten über UART verbunden sind, wurden in einem früheren Artikel zerlegt .

Lassen Sie uns die beiden verbleibenden genauer untersuchen.

Der Block „ UART-Nachricht empfangenist für das Einschalten der Sirene (Kopfhörer) verantwortlich. Grundsätzlich ist es erforderlich, ein Beispiel für den Empfang einer Nachricht über UART zu analysieren.

Zuerst prüfen wir, ob sich die empfangenen Daten im UART befinden. Wenn ja, senden wir eine an den D-Trigger-Eingang "E". In diesem Fall kopiert der Trigger den Wert vom "D" -Eingang, in den wir die ersten beiden Zeichen aus der über UART empfangenen Nachricht schreiben. Ich wollte nicht alles komplizieren, deshalb werden wir ein einfaches Schema weiter verwenden. Wir gehen davon aus, dass eine beliebige Zahl von 00 bis 99 von UART zu uns kommt. Wir übersetzen diese Zahl von einer symbolischen in eine numerische Form (ich empfehle zu lesen, wie der Konverterblock funktioniert; ich hatte einen kleinen „Stecker“ dabei). Ferner verursacht jeder Wert "> 0" am Eingang des Vorderflankendetektors ein einzelnes Signal, das den Ausgang 5 für 5 Sekunden einschaltet und im HF-PWM-Modus arbeitet.

Sie können in den Einstellungen mit der Fülldauer des RF PWM spielen, der Ton im Kopfhörer hängt davon ab.

Gehen wir weiter zum Block"Bildung der Nachricht . " Die Umsetzung mag auf den ersten Blick ungewöhnlich erscheinen. Dies erklärt sich aus der Tatsache, dass ich nicht wirklich herausgefunden habe, wie ich mit dem seriellen Bluetooth-Terminalprogramm und mit demselben Bluetooth-Protokoll in Xamarin arbeiten soll.

Ich werde ein wenig voraus sein und sagen, dass ich nicht gelernt habe, wie ich vom Controller gesendete Nachrichten auf meinem Smartphone empfange. Wenn mit dem verkabelten UART im letzten Artikel alles offensichtlich war, kann mit Bluetooth in der Praxis anstelle der gesendeten Nachricht nur der Teil gelesen werden, und die Bedeutung des übertragenen Befehls wird verletzt.

Ich entschied, dass die einfachste Lösung darin besteht, eine einzelne Nummer zu senden, die garantiert den Empfänger ohne Verlust erreicht.

In unserem Fall überwachen wir den diskreten Zustand des Reed-Schalters und des Endschalters. Das heißt, wir haben nur 4 mögliche Kombinationen: Der Reed-Schalter und der Endschalter sind ausgeschaltet, nur eine ist eingeschaltet, beide sind eingeschaltet.

Da der Reed-Schalter und der Endschalter ein diskretes Signal (0/1) geben, müssen Sie sie irgendwie unterscheiden. Dazu multiplizieren wir den Wert des Reed-Signals mit 2. Nun stellt sich heraus, dass die Summe der Signale Werte von 0 bis 3

ergibt . Jetzt analysieren wir eine nicht offensichtliche Option, wobei fünfzig zu diesem Wert hinzugefügt werden. Tatsache ist, dass CannyLab ein paar Zeichen an UART sendet, dh anstelle von 3, sagen wir 03, aber wie gesagt, es besteht die Gefahr, dass einige der Informationen verloren gehen. Ab dem Wert 01 kann das Programm auf dem Smartphone beispielsweise nur die erste „0“ lesen, und dies ist bereits ein Fehler.

Es wäre möglich, verwirrt zu werden und die Daten zu transformieren, indem beispielsweise das Zeichen „D1“ des Registers durch einen Buchstaben oder ein Leerzeichen ersetzt wird, aber ich habe beschlossen, es einfacher zu machen. Ich habe den Wert 01 in 51 (02 in 52 usw.) konvertiert. Die fünf tragen kein Signal und ich habe es auf Programmebene für ein Smartphone ausgeschaltet. Somit garantieren wir immer, dass der nützliche Teil der Nachricht erhalten bleibt.

Wir laden das Programm in die Steuerung, klicken auf „Ausführen“. Wenn alles wie geplant funktioniert, blinkt der HC-06 regelmäßig eine rote LED.

Als nächstes koppeln wir das Smartphone mit dem Adapter. Jetzt können Sie die Leistung in der Anwendung „Serielles Bluetooth-Terminal“ oder einem anderen mit ähnlichen Funktionen überprüfen.

Notieren Sie sich die Adresse des Bluetooth-Adapters. Diese wird uns im nächsten Kapitel hilfreich sein.



Wie Sie sehen können, kommen die Daten abhängig vom Zustand der Sensoren. Wenn Sie "11" senden, ist ein unangenehmes Quietschen im Kopfhörer zu hören. Wir könnten hier aufhören, aber lassen Sie uns eine primitive Anwendung skizzieren.

Das Programm für den Controller und der Quellcode des Programms für das Smartphone können von GitHub heruntergeladen werden.

Ich möchte darauf hinweisen, dass Sie nicht alles in Hardware speziell auf CANNY-Controllern implementieren müssen. Sie können ein Programm für Arduino oder einen anderen Controller schreiben, den Sie mögen. Anfangs hatte ich selbst vor, eine zusätzliche Version der Skizze für Arduino zu schreiben, aber da ich fast alle Maiferien getötet habe, hatte ich einfach nicht die Kraft, CANNY und die Smartphone-Anwendung zu verbinden.

Teil III: Schreiben einer Xamarin Android-Anwendung


Ich weiß, dass Xamarin, gelinde gesagt, nicht die beliebteste Lösung für die mobile Entwicklung ist. Und vielleicht haben Sie bereits eine Frage: "Warum habe ich es gewählt?" . Ich möchte ihm mit Worten aus dem gleichnamigen Lied von Psoya Korolenko antworten:



Ehrlich gesagt gibt es keine objektiven Gründe. Vor ein paar Jahren habe ich die Grundlagen von C # gelernt und jeder wollte sehen, was Xamarin ist. Und jetzt, aufgrund der "Selbstisolation", haben die Hände endlich erreicht.

Nun, ich möchte Sie noch einmal daran erinnern. Dies ist mein erstes Treffen mit Xamarin und dies ist meine erste Android-App. Kopieren Sie meinen Kurvencode nicht blind. Wenn Sie plötzlich eine schönere Lösung finden, verwenden Sie ihn.

Bei der Entwicklung meines Programms habe ich mich auf dieses Material verlassen. Der Artikel ist nicht besonders gekaut und auch nicht auf Spanisch, daher fand ich es immer noch angebracht, meine Variation zu diesem Thema mit Ihnen zu teilen.

Ich habe das Programm in der Visual Studio 2019 Community Edition erstellt.

Erstellen Sie zunächst ein neues leeres Android-Projekt (Xamarin) wie im Bild.



Ich habe Änderungen nur in drei Dateien vorgenommen, sie können vollständig auf GitHub angezeigt werden , und hier werden nur die wichtigen Teile analysiert:

AndroidManifest.xml

2 Berechtigungen werden zur Standardvorlage hinzugefügt:

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

activity_main.xml Der
Standardcontainer (RelativeLayout) wurde entfernt. Stattdessen wurde der LinearLayout-Container einfach hinzugefügt, weil er einfacher ist. In diesem Container sind alle Elemente vertikal ausgerichtet und erstrecken sich über die gesamte Breite des Bildschirms.

<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>

Jeder, der mit HTML-Layout oder XML ein wenig vertraut ist, kann die Struktur der Benutzeroberfläche leicht verstehen. Wir haben drei schreibgeschützte Textfelder (TextView), einen Schalter (Switch), der im Grunde wie ein Kontrollkästchen funktioniert, und eine normale Schaltfläche (Button). Elemente können durch Ziehen und Ablegen aus dem Konstruktor und im Eigenschaftenfenster oder im Code in das Formular eingefügt werden, um eine bequemere ID, Textstubs und andere Parameter festzulegen.

Es bleibt die Logik des Programms zu beschreiben.

MainActivity.cs

Unten unter dem Spoiler dient der gesamte Code der Einfachheit halber

Vollständiger MainActivity.cs-Code
// 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);
        }
    }
 }


Jetzt in Teilen.

Blöcke mit Verbindung von Namespaces, Klassendeklaration usw. Ich werde vermissen.


Wir erstellen Variablen, mit denen wir später die Elemente der Benutzeroberfläche binden:

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

Als nächstes kommt der Code aus dem Beispiel, auf das ich mich verlassen habe. Variablen (Felder), die für den Betrieb bestimmter Methoden erforderlich sind.

  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;

Hier ist es wichtig, dass wir die Adresse Ihres HC-06-Moduls in das Adressfeld eingeben.

Da dies meine erste Entwicklungserfahrung für Smartphones ist, einschließlich der Arbeit mit Xamarin, habe ich beschlossen, nichts zu komplizieren, sodass die Geräteadresse wie im ursprünglichen Beispiel festgelegt ist. Wenn Sie möchten, können Sie diesen Artikel sehen , es scheint, dass eine Aufzählung der verfügbaren Bluetooth-Geräte implementiert ist.

Mach weiter.


        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();
        }

Diese Methode wird automatisch erstellt. Unsere Aufgabe besteht darin, UI-Objekte darin den Feldern der Klasse zuzuordnen und Handler für Reaktionen auf Ereignisse anzuhängen ( startSiren.Click bltSwitch.CheckedChange).

Überprüfen der Verbindung über 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();
            }
        }

Schalten Sie die Sirene ein. Im Wesentlichen nur die Zeichen "11" an die Steuerung senden:


   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";
        }

Überprüfen des Status des Schalters (wenn er nach rechts verschoben wird, bedeutet dies, dass er eingeschaltet ist):

   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);
                    }
                }
            }
        }

Wenn Sie einschalten, beginnen wir die Verbindung mit Bluetooth.

Die Implementierung der Verbindung selbst:

   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();

        }

Und hier ist eine der wichtigsten Methoden - direktes Lesen von Daten:


    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;
                    }
                }
            });
        }

Ich habe viele Elemente der Methode belassen, wie im Beispiel, so wie ich es verstehe. Zuerst wird eine Verbindung zum Datenstrom hergestellt. Wenn sich etwas im Puffer mit den gelesenen Daten befindet, wird es in eine Variable eingelesen valor. Außerdem löschen wir, wie versprochen, einfach die Zahl „5“.

Als nächstes entfernen wir alle Zeichen außer den Zahlen aus der gelesenen Nachricht. string command = new string(valor.Where(char.IsDigit).ToArray());

Nun, danach ist alles einfach, je nachdem, welche Zahl zu uns gekommen ist, zeigen wir diesen oder jenen Status in der Benutzeroberfläche an.

Ich habe diese beiden Methoden nicht grundlegend geändert:

  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);
        }
    }
 }

Soweit ich weiß, implementiert dieser Codeblock das Senden einer Nachricht und eines Ereignishandlers, um die Zugriffsberechtigung für Bluetooth zu überschreiten.

Nun, das ist alles, was Sie noch tun müssen, um eine Smartphone-Verbindung zum Debuggen der Anwendung einzurichten .

Seltsamerweise funktioniert es aber:



Teil IV: Schlussfolgerung


So funktioniert das Programm in Form von Sachleistungen:



Das war meine erste Erfahrung bei der Entwicklung von Anwendungen für ein Smartphone auf Android.

Ich möchte darauf hinweisen, dass VS 2019 und Xamarin auf meinem alten Computer sehr langsam arbeiten.

Bei der ersten Montage des Projekts habe ich es wirklich geschafft, diese weichen französischen Brötchen zu essen und Tee zu trinken. Auch die Anwendung selbst erwies sich als ehrlich gesagt miserabel, der Ein / Aus-Schalter funktioniert nicht sehr bequem, aber andererseits, da ich nur wenig mit den grundlegenden Entwicklungstechniken für .NET vertraut bin und überhaupt kein Programmierer bin, könnte ich sogar Umreißen Sie Ihre erste Bewerbung an einem Tag, ohne ein einziges Tutorial oder eine einzige Lektion durchzugehen. Daher ist die Eingabeschwelle zum Erstellen einer Elementaranwendung recht niedrig.

Soweit ich weiß, können CANNY-Controller zum Tunen von Autos verwendet werden, insbesondere von Haushaltsautos, so dass es durchaus möglich ist, eine Art „Feature“ zu erstellen und eine Anwendung für ein Smartphone darauf zu schreiben. Beachten Sie vor allem, dass die Controller-Ausgänge bei Stromversorgung über das Bordnetz des Fahrzeugs dieselbe Spannung wie der Eingang haben (z. B. 12 V anstelle von 5 V). Vergessen Sie nicht, den Bluetooth-Adapter zu schützen, damit er nicht versehentlich ausfällt.

Der Artikel erwies sich als sehr mühsam für mich, ich hoffe, dass nicht alles umsonst war und es Ihnen gefallen wird.

All Articles