برمجة ونقل البيانات إلى Arduino عبر الأثير باستخدام ESP8266. الجزء الثالث. مرحبًا ANDROID

أقدم لكم ، أيها القراء الأعزاء لـ GeekTimes ، مقالة أخرى من الدورة حول استخدام شريحة ESP8266 كجسر لاسلكي لأجهزة التحكم الدقيقة AVR ، باستخدام منصة الأجهزة Arduino Uno (Nano) كمثال. هذه المرة ، من أجل الرحلة إلى القمر للتحكم في النظام الأساسي ، نستخدم جهازًا يستند إلى ANDROID بدلاً من جهاز كمبيوتر. حسنًا ، على سبيل المثال ، هاتف ذكي.



التفاصيل تحت القطع:

لعملنا ، سنستخدم الأدوات الموضحة في المقالة السابقة - مبرمج BABUINO اللاسلكي ووحدة MPDE (وحدة البرنامج وتبادل البيانات) المنقولة في ESP8266.

كما اتضح من ردود الفعل من المستخدمين ، المبرمج نفسه ، بشكل عام ، جاء إلى المحكمة وحتى بعض الأفراد يستخدمونه بنجاح. حسنًا ، في الأساس ، الشيء مناسب حقًا ؛ لقد أطلقت التطبيق تحت Windows ، واخترت الملف السداسي من المجلد المطلوب وهذا كل شيء - في بضع ثوانٍ البرنامج في الجهاز الصحيح دون أي أسلاك. شيء آخر هو أنه دون جدوى ، بحماسة شديدة ، هاجمت مستخدمي برنامج ARDUINO الذين يكتبون في Wiring C ويستخدمون ARDUINO IDE مع رسوماته ومكتباته. بالطبع ، يفعل الجميع ما هو مناسب له - سواء في Arduin Wiring C أو C من استوديو AVR. ولكن في النهاية ، قرر بعض المستخدمين لسبب ما على الفور أن المبرمج لا يتوافق بأي حال من الأحوال مع برنامج ARDUINO.

في الواقع ، لا توجد مشكلات توافق بالطبع. قم أيضًا بتجميع الرسم التخطيطي الخاص بك في المكان المناسب لك لحالة الملف السداسي وإرساله بسهولة من خلال مبرمج لاسلكي إلى Arduino UNO أو NANO.

تبادل البيانات ضمن برنامج ARDUINO لا يسبب أي مشاكل أيضًا. اكتب الخطوط السحرية:

Serial.begin (9600) ؛

ثم شيء مثل:

ReceByte = Serial.read () ، // قراءة البايت من المخزن المؤقت

أو:

Serial.write (ReceByte) ؛ // بايت سجل

ويمكنك تبادل تدفقات البايت عبر WI-FI بهدوء تام. بالنسبة إلى متحكم AVR يرسل إلى ESP8266 ويستقبل وحدات البايت من هناك عبر منفذ UART التسلسلي ، والذي ، كما نرى ، يمكن لأي إنساني تكوين العمل الذي في Arduino.

نعود الآن إلى موضوع هذه المقالة. من أجل التحكم في الروبوت عبر الهاتف الذكي ، بالطبع ، يجب عليك كتابة التطبيق المناسب لهذا الهاتف الذكي.

كشخص قدم هذه العملية قبل شهر غامض للغاية ، يمكنني الآن أن أعلن بكل المسؤولية أن الأمر ليس معقدًا بشكل أساسي. ما لم يكن لديك بالطبع بعض المعرفة الأساسية على الأقل في مجال جافا.

عند كتابة تطبيقات Android ، تتم كتابة شفرة المصدر بلغة Java ، ثم يتم تجميعها في Java bytecode القياسي باستخدام أدوات Java التقليدية. ثم تحدث أشياء أخرى مثيرة للاهتمام للشفرة ، لكننا لا نحتاج إلى هذه التفاصيل هنا.

يبدو أنه لا تزال هناك فرص لكتابة الطلبات في لغة C للعمال المتشددين المشهورين الذين يسجلون بالثواني النانوية ، وأيضًا في مكان ما هناك نوع من الحزمة لترجمة شفرتك من Python ، ولكن لا يمكنني أن أقول أي شيء هنا ، لأنني اتخذت الخيار الصحيح لفترة طويلة .

لذا ، فإن حزمة برامج Java و Android Studio - بيئة تطوير متكاملة (IDE) للعمل مع منصة Android استنادًا إلى برنامج IntelliJ IDEA من JetBrains ، أداة التطوير الرسمية لتطبيقات Android.



إذا كنت تعمل بالفعل مع برنامج IntelliJ IDEA ، فستفاجأ بسلاسة من الواجهة المألوفة.

تعرفت على أساسيات بناء التطبيقات من كتاب B. Phillips و C. Stewart - برمجة "ANDROID" للمحترفين. "كما أفهمها ، ينظر المحترفون إلى القراء الذين هم على الأقل على دراية بسيطة بـ Java SE. هناك شيء معقد في هذا الكتاب لم أجد ، ولأغراضنا ، ستكون الفصول العشرة الأولى من الكتاب كافية تمامًا ، لحسن الحظ ، يتم تقديم جميع أمثلة التعليمات البرمجية فيه عند العمل مع Android Studio المذكور أعلاه.

يمكن تنفيذ تطبيقات التصحيح إما على محاكي برامج أو مباشرة على هاتف ذكي عن طريق تحويله إلى "وضع المطور".

في مقال سابق ، تم وصف التحكم في العربة من خلال تطبيق windows على Windows. أي أن جميع التعليمات البرمجية لإنشاء اتصالات HTTP و UDP ، بالإضافة إلى منطق التحكم ، موجودة بالفعل من الناحية النظرية. لذلك ، بعد اعتماد شعار أوراكل "مكتوب في مكان واحد ، يعمل في كل مكان" ، نقوم ببساطة بنقل هذه الفئات إلى برنامج جديد لتطبيقات Android. لكن واجهة المستخدم الرسومية هي واجهة مستخدم رسومية ، ولأسباب واضحة ، يجب عليك المغادرة حيث كانت. ولكن من ناحية أخرى ، على Android ، يتم كل شيء بشكل مشابه وسريع جدًا ، لذلك لن نبقى في الخاسر.

ادفع إصبعك على الشاشة



لذا ، قمنا بإنشاء مشروع جديد "FourWheelRobotControl" في Android Studio.
هذا تطبيق بسيط وسيتألف من النشاط

فئة MainActivity.java
import android.content.Context; import android.hardware.Sensor; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private ImageButton mButtonUP; private ImageButton mButtonDOWN; private ImageButton mButtonLEFT; private ImageButton mButtonRIGHT; public static byte direction = 100; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new HTTP_client(40000); new Udp_client(); mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonUP.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 3; } } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonDOWN = (ImageButton) findViewById(R.id.imageButtonDown); mButtonDOWN.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 4; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonLEFT = (ImageButton) findViewById(R.id.imageButtonLeft); mButtonLEFT.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 1; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); mButtonRIGHT = (ImageButton) findViewById(R.id.imageButtonRight); mButtonRIGHT.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { direction = 2; Toast.makeText(MainActivity.this, " " + direction, Toast.LENGTH_SHORT).show(); } if (event.getAction() == MotionEvent.ACTION_UP) { direction = 100; } return false; } }); } 

والتخطيط:

التخطيط
  /spoiler/ activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="mikhail_akhmetov.fourweelsrobotcontrol.MainActivity"> <ImageButton android:id="@+id/imageButtonRight" style="@android:style/Widget.Holo.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintHorizontal_bias="0.417" app:layout_constraintLeft_toRightOf="@+id/imageButtonLeft" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.513" app:srcCompat="@android:drawable/ic_media_ff"/> <ImageButton android:id="@+id/imageButtonUP" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginBottom="8dp" android:layout_marginTop="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/imageButtonDown" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.486" app:srcCompat="@android:drawable/arrow_up_float"/> <ImageButton android:id="@+id/imageButtonDown" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginBottom="57dp" android:layout_marginLeft="8dp" android:background="@android:color/holo_orange_dark" android:fadingEdge="horizontal" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintHorizontal_bias="0.487" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:srcCompat="@android:drawable/arrow_down_float" android:layout_marginStart="8dp"/> <ImageButton android:id="@+id/imageButtonLeft" style="@android:style/Widget.ImageButton" android:layout_width="52dp" android:layout_height="52dp" android:layout_marginLeft="94dp" android:layout_marginStart="94dp" android:background="@android:color/holo_orange_dark" app:layout_constraintBottom_toTopOf="@+id/linearLayout" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.513" app:srcCompat="@android:drawable/ic_media_rew" /> <LinearLayout android:id="@+id/linearLayout" android:layout_width="368dp" android:layout_height="227dp" android:layout_marginBottom="11dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:orientation="vertical" android:weightSum="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <TextView android:id="@+id/textViewX" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewZ" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.23" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 


ليس من الضروري الكتابة باستخدام الأقلام ، بل يتم إنشاؤها تلقائيًا بعد إبداعاتك في المحرر.

الآن ننقل فصلين فقط من البرنامج الوارد في المقالة السابقة:

HTTP_client.java
 import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.InetAddress; import java.net.Socket; public class HTTP_client extends Thread{ int port; String s; public static String host_address="192.168.1.138";//    public String Greetings_from_S; HTTP_client(int port) { this.port = port; start(); } public void run() { try (Socket socket = new Socket(host_address,port)){ PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); pw.println("stop data\r");//  ,    pw.println("data\r");// Greetings with SERVER Greetings_from_S = br.readLine(); if (Greetings_from_S.equals("ready")) { new Udp_client(); } } catch (Exception e) { e.printStackTrace(); } } } 


Udp_clent.java
 import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class Udp_client extends Thread { int i =0; byte [] data = {0}; int udp_port=50000; InetAddress addr; DatagramSocket ds; public Udp_client() { try { ds = new DatagramSocket(); addr = InetAddress.getByName(HTTP_client.host_address); } catch (Exception e) { } start(); } public void run() { while (true) { byte temp = MainActivity.direction; String s = "" + MainActivity.direction; data = s.getBytes(); if(temp!=100 ) { DatagramPacket pack = new DatagramPacket(data, data.length, addr, udp_port); try { ds.send(pack); i=0; Thread.sleep(200); } catch (Exception e) { } } else { if(i==0) { s = "" + 0; data = s.getBytes(); DatagramPacket pack = new DatagramPacket(data, data.length, addr, udp_port); try { ds.send(pack); Thread.sleep(200); } catch (Exception e) { } } i=1;//     } } } } 

جوهر البرنامج لا يزال هو نفسه. تقوم MainActivity أولاً بتشغيل عملاء HTTP و UDP ، ومن ثم التقاط الضغط على الأزرار والاكتئاب ، وإرسال رمز دفع الاتجاه لتشكيل حزمة UDP. ومن هناك كل شيء موجود بالفعل - "للأمام" و "للخلف" و "لليسار" و "لليمين" وعندما تضغط على "إيقاف" ، يغادرون عبر WI-FI في عربة.

بالإضافة إلى كل هذا ، نحتاج إلى تعديل ملف ما يسمى البيان بشكل طفيف ، والذي ، مرة أخرى ، يتم إنشاؤه من تلقاء نفسه.

البيان هو ملف XML يحتوي على بيانات وصفية تصف تطبيق Android الخاص بك. يسمى ملف البيان دائمًا AndroidManifest.xml ويوجد في دليل التطبيق / البيان لمشروعك.

صحيح أن هناك القليل من العمل بالنسبة لنا.

منع دوران الشاشة:

 android:screenOrientation="portrait" 

نحن نسمح بالعمل على الإنترنت:

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

وهنا كل شيء تماما.

AndroidManifest.xml
 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="mikhail_akhmetov.fourweelsrobotcontrol"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:screenOrientation="portrait" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> <uses-permission android:name="android.permission.INTERNET"/> </manifest> 


عند بدء التشغيل ، يجب أن نرى شيئًا مثل:



هذا كل شيء في الأساس. الآن يمكن التحكم في العربة من هاتف محمول. التطبيق بسيط للغاية ، لأنه تطبيق تجريبي بدون أي "صفارات وتزييفات" ، مثل البحث عن عربة على شبكة منزلية والاتصال والفصل والميزات المفيدة الأخرى التي تجعل الحياة أسهل ، ولكن تجعل الشفرة صعبة الفهم.

من ناحية أخرى ، فإن العمل باستخدام الأزرار التي تظهر على الشاشة هو نفسه
"كيف تشرب الفودكا فقط ، حتى من الرقبة - لا يوجد فيها شيء سوى ضعف الروح والضجيج."
وكانت فينييا إيروفيف محقة في هذا بالطبع.

من المثير للاهتمام ، على سبيل المثال ، توجيه عربة بمساعدة مقاييس التسارع القياسية لنفس الهاتف الذكي.

علاوة على ذلك ، يتم تنفيذ هذه الميزة أيضًا ببساطة شديدة ، من خلال ما يسمى النوايا. صحيح أن إنشاء أهدافك الخاصة أكثر صعوبة من استخدام الأهداف الجاهزة. لحسن الحظ ، لا أحد يمنع استخدام الجاهزة.

التسارع في الكتل



لذلك ، فإن الكود الخاص بنا في MainActivity (وفيه فقط) سيتغير إلى الحد الأدنى.

أضف متغيرات لمقياس التسارع:

 private SensorManager mSensorManager; private Sensor mOrientation; private float xy_angle; private float xz_angle; 

نحصل على جهاز الاستشعار نفسه من النظام وتسجيله كمستمع.

 mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL); 

نقوم بتطبيق واجهة المستمع نفسها:

 public class MainActivity implements SensorEventListener 

وسنكتب أربع طرق إلزامية لن نستخدم منها سوى الأخيرة. طريقة تعمل عند تغيير قراءات مقياس التسارع. في الواقع ، كنت أرغب في استجواب مقياس التسارع بنفسي ، مثل الأجهزة الطرفية العادية مع فترة حوالي 100 مللي ثانية ، لأنه كان هناك شك (بسبب الاسم onChanged) أن الطريقة نجحت في كثير من الأحيان. ولكن هناك كل شيء خاص وتين للواجهات التي ستحصل عليها.

 @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //    } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override public void onSensorChanged(SensorEvent event) {} //   

نتيجة لذلك ، تتخذ MainActivity.java الشكل التالي
 import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.content.Context; import android.hardware.Sensor; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.ImageButton; import android.widget.TextView; public class MainActivity extends AppCompatActivity implements SensorEventListener { private ImageButton mButtonUP; private ImageButton mButtonDOWN; private ImageButton mButtonLEFT; private ImageButton mButtonRIGHT; public static byte direction = 100; private SensorManager mSensorManager; private Sensor mOrientation; private float xy_angle; private float xz_angle; private int x; private int y; private TextView xyView; private TextView xzView; private TextView zyView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new HTTP_client(40000); new Udp_client(); mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //    mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); //    mSensorManager.registerListener(this, mOrientation, SensorManager.SENSOR_DELAY_NORMAL); xyView = (TextView) findViewById(R.id.textViewX); // xzView = (TextView) findViewById(R.id.textViewY); //       zyView = (TextView) findViewById(R.id.textViewZ);//   "direction" mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonDOWN = (ImageButton) findViewById(R.id.imageButtonDown); mButtonLEFT = (ImageButton) findViewById(R.id.imageButtonLeft); mButtonRIGHT = (ImageButton) findViewById(R.id.imageButtonRight); //    } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { //    } @Override protected void onResume() { super.onResume(); } @Override protected void onPause() { super.onPause(); } @Override public void onSensorChanged(SensorEvent event) { //   xy_angle = event.values[0]*10; // XY xz_angle = event.values[1]*10; // XZ x=-(int) xy_angle*1; y=-(int) xz_angle*1; xyView.setText(" x = "+ String.valueOf(x)); xzView.setText(" y = "+String.valueOf(y)); zyView.setText(" direction "+String.valueOf(direction)); if(y>-40&&y<-20){ direction=100;//   ,   ,     if (x>10){//   10  30  20  direction=(byte)(x+30); if (direction>60){direction=60;} } if(x<-10){ direction=(byte)(-x+50); if (direction>80){direction=80;} } } else { if (y > -20) {//  ,  -20: 20  40  direction = (byte) (y / 2 + 10); if (direction > 20) { direction = 20; } ; } if (y < -40) {//  ,  -40: -80  40  direction = (byte) (-y - 20); if (direction > 40) { direction = 40; } ; } } } } //   direction 100  // 1-20  ,   -20 // 21-40  ,   -40 // 41-60 ,  10 // 61-80 ,   -10 


يعرض البرنامج المستشعرات على محورين على شاشة الهاتف الذكي. بدلاً من المحور الثالث ، الذي لا يستخدم ، يتم عرض متغير الاتجاه "اتجاه". ويتم تشغيل نفس البيانات في شكل دفق بايت إلى سلة التسوق. ومع ذلك ، نظرًا لحقيقة أن الدفق هو بايت بحت ، سيكون من الصعب تحديد المكان الذي سيكون فيه الأمر "للأمام" أو "الإيقاف". لذا فعلت ذلك: كل اتجاه وزاوية ميل له نطاق أرقام خاص به. بشكل تقريبي ، 1-20 هي "للأمام" بالسرعة المقابلة ، 21-40 هي "للخلف" وهكذا. بالطبع ، سيكون من الممكن نقل البيانات الخالصة عبر UDP ، ويجب تعيين أوامر التحكم نفسها عبر بروتوكول TCP ، وهذا بالتأكيد سيكون أكثر صحة. ولكن لهذا تحتاج إلى تعديل البرنامج على ESP8266 نفسه ، والذي لا أريده بعد.

لذا ، تدور العربة حول الشقة ، وتتفاعل بشكل حساس مع منحدرات GalaxyS7 ، ولكن حتى هذا ، كما كان يقول Venya سيئ السمعة ، لا يزال ليس كذلك.

"الآن أقدم لكم آخر وأفضل. قال الشاعر "تاج العمل فوق كل شيء". باختصار ، أقدم لكم كوكتيل "Offal Off" ، وهو مشروب يحجب كل شيء. لم يعد هذا مشروبًا - إنها موسيقى المجالات. „

في عصر سيري وأليكسا هذا ، هل هناك شيء لتدوير يديك؟ دع التحكم الصوتي يطيع!

والاستماع إلي الآن!



أقتبس:

في الواقع ، يعد العمل مع التعرف على الكلام وتركيب الكلام في Android أمرًا بسيطًا للغاية. جميع الحسابات المعقدة مخفية عنا في مكتبة أنيقة إلى حد ما مع واجهة برمجة تطبيقات بسيطة. يمكنك إتقان هذا الدرس حتى إذا كانت لديك معرفة سطحية جدًا بالبرمجة لنظام Android.

في الواقع ، تحول كل شيء إلى أخرق بالنسبة لي ، ولكن على الأرجح لأنني استخدمت الخيار الأبسط ، ولم أحفر في واجهة برمجة التطبيقات هذه بشكل صحيح. كل شيء يتم أيضًا من خلال المقاصد ، والتي نلجأ إليها إلى محرك Google الصوتي ، وبالتحديد إلى وظيفة التعرف على الكلام. لذلك ، تحتاج إلى إنترنت يعمل.

مرة أخرى يتغير MainActivity.java فقط ، على الرغم من أنني غيرت التخطيط أكثر قليلاً (أربعة أزرار أصبحت الآن غير مجدية تمامًا هناك ، يكفي واحد).

تمت إضافة ما يلي إلى MainActivity.java:

نفس القصد:

 Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, ", ,  -??? "); startActivityForResult(intent, Print_Words); 

وماذا ترجع:

 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //    : if (requestCode==Print_Words && resultCode==RESULT_OK) { //     ,   : ArrayList<String>result=data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); //     TextView: stroka_otveta = result.toString(); } 

ويعيد مجموعة من الكلمات المتشابهة ، وفي "شكل قمامة" بدلاً من ذلك ، مع جميع أنواع الأقواس والفواصل. وعليك فقط اختيار كلمة مشابهة لتلك التي قلتها. حسنًا ، وبناءً على ذلك ، إذا تم التقاط كلمة "إلى الأمام" ، فإننا نمضي قدمًا ، إذا كانت "حق" ثم إلى اليمين وما إلى ذلك. بالطبع ، يجب أن نأخذ في الاعتبار حيث من خلال "E" ، حيث يتم إرفاق الفاصلة الإضافية (قطعت الأقواس ، لكن لم يكن لدي ما يكفي من القوة للفواصل).

في المجموع ، أصبح نص MainActivity.java نفسه كذلك
 import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageButton; import android.widget.TextView; import java.util.ArrayList; import android.content.Intent; import android.speech.RecognizerIntent; public class MainActivity extends AppCompatActivity { private ImageButton mButtonUP; public static byte direction = 100; public String stroka_otveta; private static final int Print_Words = 100; private TextView EnteredText1; private TextView EnteredText2; public static TextView EnteredText3; private boolean slovo_raspoznano =false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new Udp_client(); new HTTP_client(40000); EnteredText1 = (TextView) findViewById(R.id.textViewX); // EnteredText2 = (TextView) findViewById(R.id.textViewY); // EnteredText3 = (TextView) findViewById(R.id.textViewZ); // mButtonUP = (ImageButton) findViewById(R.id.imageButtonUP); mButtonUP.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN){ if(HTTP_client.ok){ // RecognizerIntent        : EnteredText3.setText(" http  "); Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH); intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM); intent.putExtra(RecognizerIntent.EXTRA_PROMPT, ", ,  -??? "); startActivityForResult(intent, Print_Words); } else { EnteredText3.setText("  "); } } if (event.getAction() == MotionEvent.ACTION_UP ){ } return false; } }); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //    : if (requestCode==Print_Words && resultCode==RESULT_OK) { //     ,   : ArrayList<String>result=data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS); //     TextView: stroka_otveta = result.toString(); } StringBuffer sb = new StringBuffer(stroka_otveta); sb.deleteCharAt(stroka_otveta.length()-1); sb.deleteCharAt(0); stroka_otveta=sb.toString(); String[] words = stroka_otveta.split("\\s"); //        () //    for(int i = 0; i< words.length;i++) { if(words[i].equals(",")||words[i].equals("")) { direction = 1; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")||words[i].equals("")){ direction=2; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals("")){ direction=4; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals(",")|| words[i].equals("") || words[i].equals("")){ direction=3; slovo_raspoznano=true; stroka_otveta=words[i]; } if(words[i].equals(",")|| words[i].equals(",")|| words[i].equals("") || words[i].equals("")){ direction=100; slovo_raspoznano=true; stroka_otveta=words[i]; } } if(!slovo_raspoznano){ direction=100; stroka_otveta=" ,   ... "; } EnteredText1.setText(" "+direction+" " +stroka_otveta); slovo_raspoznano=false; super.onActivityResult(requestCode, resultCode, data); } } 

حسنا ، حتى تخطيط كومة مع زر واحد

Activity_main.xml.
  <?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="mikhail_akhmetov.fourwheelsrobotandroidvoice.MainActivity"> <ImageButton android:id="@+id/imageButtonUP" style="@android:style/Widget.ImageButton" android:layout_width="160dp" android:layout_height="146dp" android:layout_marginTop="8dp" android:background="@android:color/holo_orange_dark" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@android:drawable/arrow_up_float" android:layout_marginBottom="8dp" app:layout_constraintBottom_toTopOf="@+id/linearLayout"/> <LinearLayout android:id="@+id/linearLayout" android:layout_width="368dp" android:layout_height="227dp" android:layout_marginBottom="11dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_marginStart="8dp" android:orientation="vertical" android:weightSum="1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_bias="1.0" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"> <TextView android:id="@+id/textViewTitle" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="   " android:textColor="@android:color/holo_red_dark"/> <TextView android:id="@+id/textViewX" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewY" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.28" /> <TextView android:id="@+id/textViewZ" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="0.23" /> </LinearLayout> </android.support.constraint.ConstraintLayout> 

أكثر شيء مدهش هو أنه يركب ويستمع إلى الصوت (كقاعدة عامة). ولكن ، بالطبع ، واجهة الفرامل ؛ بينما تقول ، حتى يتم التعرف عليها وستعود ؛ باختصار ، اختر سرعة صغيرة مقدمًا أو تكون الغرفة بالعكس أوسع.

هذا كل شيء لهذا اليوم ، سأكون سعيدًا إذا أحببته.

Source: https://habr.com/ru/post/ar409107/


All Articles