diff --git a/MobileApp/.idea/misc.xml b/MobileApp/.idea/misc.xml index 5fb06df..7b77ba6 100644 --- a/MobileApp/.idea/misc.xml +++ b/MobileApp/.idea/misc.xml @@ -25,7 +25,7 @@ - + diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/Communication.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/Communication.java index a782e95..190edd1 100644 --- a/MobileApp/app/src/main/java/com/example/lfrmobileapp/Communication.java +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/Communication.java @@ -11,53 +11,40 @@ import java.util.Iterator; import java.util.Objects; public class Communication { - public boolean sendData(String data, String ip, int port) { - try { - Socket socket = new Socket(ip, port); - DataOutputStream DOS = new DataOutputStream(socket.getOutputStream()); - DOS.writeUTF(data); - socket.close(); - } catch (Exception e) { - e.printStackTrace(); - return true; //ToDo: change to false to test connection - currently always true is delivered - } - return true; - } - public String telegram(int[] wheels, int strenght){ - String tel = ""; - tel += "0;"; //Manuel mode + String tel = "aa"; + tel += "0"; //Manuel mode for(int i = 0; i < wheels.length; i++){ if(wheels[i] == 1){ - tel += Float.toString(((float)strenght)/100) + ";"; + tel += ";" + Float.toString(((float)strenght)/100) ; }else if(wheels[i] == -1) - tel += Float.toString(((float)-strenght)/100) + ";"; + tel += ";" + Float.toString(((float)-strenght)/100); else{ - tel += "0.00;"; + tel += ";0.00"; } } - Log.v("TAG", tel + "\n"); + tel += "zz"; return tel; } public String telegram(boolean startStop, ArrayList list){ String tel = ""; - tel += "1;"; //Autonomous mode + tel += "1"; //Autonomous mode if(startStop){ - tel += "1;"; + tel += ";1"; }else{ - tel += "0;"; + tel += ";0"; } for (String i : list) { if(i.equals("Links")){ - tel += "0;"; + tel += ";0"; }else if (i.equals("Rechts")){ - tel += "1;"; + tel += ";1"; } } - Log.v("TAG", tel + "\n"); return tel; } + } \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/DataTransferAsyncTask.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/DataTransferAsyncTask.java new file mode 100644 index 0000000..dcf4e01 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/DataTransferAsyncTask.java @@ -0,0 +1,49 @@ +package com.example.lfrmobileapp; + +import android.os.AsyncTask; +import android.util.Log; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class DataTransferAsyncTask extends AsyncTask { + private static final double sendRatePerSecond = 4.0; + private boolean connected; + private final ExtendedSocket socket; + private BlockingQueue blockingQueue; + + public DataTransferAsyncTask(ExtendedSocket socket) { + this.socket = socket; + this.connected = true; + this.blockingQueue = new LinkedBlockingQueue<>(); + } + + public void writeTelegram(String telegram) { + // Schau mal hier bei Fehler + blockingQueue.offer(telegram); + } + + @Override + protected Void doInBackground(Void... params) { + while(!isCancelled() && connected) { + try { + synchronized (socket) { + String message = blockingQueue.poll((long) (1000.0/sendRatePerSecond), TimeUnit.MILLISECONDS); + if(message != null){ + Log.v("TAG", message + "\n"); + socket.sendMessage(message); + } + } + } catch (Exception e) { + e.printStackTrace(); + connected = false; + } + } + return null; + } +} diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ExtendedSocket.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ExtendedSocket.java new file mode 100644 index 0000000..6041782 --- /dev/null +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ExtendedSocket.java @@ -0,0 +1,25 @@ +package com.example.lfrmobileapp; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; + +public class ExtendedSocket { + private final Socket socket; + + public ExtendedSocket(Socket socket) { + this.socket = socket; + } + + public void sendMessage(String message) throws IOException { + synchronized (socket){ + DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream()); + outputStream.writeBytes(message); + outputStream.flush(); + } + } + + public void closeSocket() throws IOException { + this.socket.close(); + } +} diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java index 55d2ee2..6f60d74 100644 --- a/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/MainActivity.java @@ -3,6 +3,7 @@ package com.example.lfrmobileapp; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; +import android.widget.Toast; import com.google.android.material.bottomnavigation.BottomNavigationView; @@ -14,11 +15,21 @@ import androidx.navigation.ui.NavigationUI; import com.example.lfrmobileapp.databinding.ActivityMainBinding; - +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; public class MainActivity extends AppCompatActivity { private ActivityMainBinding binding; + private ExtendedSocket socket; + private DataTransferAsyncTask dataTransferAsyncTask; + public Boolean connected = false; @Override protected void onCreate(Bundle savedInstanceState) { @@ -38,5 +49,43 @@ public class MainActivity extends AppCompatActivity { NavigationUI.setupWithNavController(binding.navView, navController); } + public boolean connectToWifi(String ipAddress, int port){ + ExecutorService executor = Executors.newSingleThreadExecutor(); + Future future = executor.submit(() -> { + Socket tempSocket = new Socket(); + tempSocket.connect(new InetSocketAddress(ipAddress, port), 1000); + try { + socket = new ExtendedSocket(tempSocket); + socket.sendMessage("Verbindung aufbauen"); + } catch (Exception e) { + socket.closeSocket(); + return false; + } + return true; + }); + + try { + connected = future.get(); + } catch (InterruptedException e) { + System.err.println("InterruptedException: " + e.getMessage()); + } catch (ExecutionException e) { + System.err.println("ExecutionException: " + e.getCause().getMessage()); + } + + executor.shutdown(); + + if(connected){ + dataTransferAsyncTask = new DataTransferAsyncTask(socket); + dataTransferAsyncTask.execute(); + return true; + }else{ + return false; + } + } + + public void sendTelegram(String telegram) + { + this.dataTransferAsyncTask.writeTelegram(telegram); + } +} -} \ No newline at end of file diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java index d8e30b4..b642cb3 100644 --- a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/dashboard/DashboardFragment.java @@ -18,6 +18,8 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import com.example.lfrmobileapp.Communication; +import com.example.lfrmobileapp.DataTransferAsyncTask; +import com.example.lfrmobileapp.MainActivity; import com.example.lfrmobileapp.R; import com.example.lfrmobileapp.databinding.FragmentAutomatikBinding; @@ -27,20 +29,22 @@ import java.util.Arrays; import kotlin.collections.UArraySortingKt; +// Autonomous Mode public class DashboardFragment extends Fragment { - - String ipKey = "ipkey"; - String portKey = "portkey"; - - String ipAddress = "192.168.0.1"; - int port = 8000; - Communication com = new Communication(); private FragmentAutomatikBinding binding; + MainActivity mainActivity; + //Keys for Shared Preferences String listKey = "listkey"; + @Override + public void onAttach(Context context) { + super.onAttach(context); + mainActivity = (MainActivity) context; + } + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { DashboardViewModel dashboardViewModel = @@ -59,17 +63,16 @@ public class DashboardFragment extends Fragment { //Get Arraylist from Shared Preferences String ArrayList autoList = stringToArraylist(sharedPref.getString(listKey, "")); - ipAddress = sharedPref.getString(ipKey, ""); - port = sharedPref.getInt(portKey, -1); - binding.startAutomatic.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - if(isChecked){ - com.sendData(com.telegram(true, autoList), ipAddress, port); - }else{ - com.sendData(com.telegram(false, autoList), ipAddress, port); + if (mainActivity.connected){ + if(isChecked){ + mainActivity.sendTelegram(com.telegram(true, autoList)); + }else{ + mainActivity.sendTelegram(com.telegram(false, autoList)); + } } } }); diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java index 0a9edaf..e81f938 100644 --- a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/home/HomeFragment.java @@ -1,9 +1,12 @@ package com.example.lfrmobileapp.ui.home; +import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; +import android.util.Log; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; @@ -15,6 +18,8 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import com.example.lfrmobileapp.Communication; +import com.example.lfrmobileapp.DataTransferAsyncTask; +import com.example.lfrmobileapp.MainActivity; import com.example.lfrmobileapp.R; import com.example.lfrmobileapp.databinding.FragmentManuellBinding; import com.example.lfrmobileapp.ui.notifications.NotificationsFragment; @@ -31,10 +36,20 @@ public class HomeFragment extends Fragment { String ipAddress = "192.168.0.1"; int port = 8000; + MainActivity mainActivity; + Communication com = new Communication(); + long lastOnMoveCall = System.currentTimeMillis(); + private FragmentManuellBinding binding; + @Override + public void onAttach(Context context) { + super.onAttach(context); + mainActivity = (MainActivity) context; + } + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { HomeViewModel homeViewModel = @@ -54,54 +69,99 @@ public class HomeFragment extends Fragment { final TextView textView = binding.textHome; homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText); - binding.rotateLeft.setOnClickListener(new View.OnClickListener(){ + + + binding.rotateLeft.setOnTouchListener(new View.OnTouchListener(){ + @SuppressLint("ClickableViewAccessibility") @Override - public void onClick(View v){ - com.sendData(com.telegram(new int[]{-1, 1, -1, 1}, 100), ipAddress, port); - }; + public boolean onTouch(View v, MotionEvent event) { + boolean send = false; + if (System.currentTimeMillis() - lastOnMoveCall > 250){ + send = true; + lastOnMoveCall = System.currentTimeMillis(); + } + if (send && mainActivity.connected) { + if (event.getAction() == MotionEvent.ACTION_UP) { + binding.rotateLeft.performClick(); + mainActivity.sendTelegram(com.telegram(new int[]{0, 0, 0, 0}, 0)); + return true; + } else { + mainActivity.sendTelegram(com.telegram(new int[]{-1, 1, -1, 1}, 100)); + } + } + return false; + } }); - binding.rotateRight.setOnClickListener(new View.OnClickListener(){ + binding.rotateRight.setOnTouchListener(new View.OnTouchListener(){ + @SuppressLint("ClickableViewAccessibility") @Override - public void onClick(View v){ - com.sendData(com.telegram(new int[]{1, -1, 1, -1}, 100), ipAddress, port); - }; + public boolean onTouch(View v, MotionEvent event) { + boolean send = false; + if (System.currentTimeMillis() - lastOnMoveCall > 250){ + send = true; + lastOnMoveCall = System.currentTimeMillis(); + } + if (send && mainActivity.connected){ + if(event.getAction() == MotionEvent.ACTION_UP){ + binding.rotateRight.performClick(); + mainActivity.sendTelegram(com.telegram(new int[]{0, 0, 0, 0}, 0)); + return true; + }else{ + mainActivity.sendTelegram(com.telegram(new int[]{1, -1, 1, -1}, 100)); + } + } + return false; + } }); + JoystickView joystick = (JoystickView) binding.joystick; joystick.setOnMoveListener(new JoystickView.OnMoveListener() { @Override public void onMove(int angle, int strength) { + boolean send = false; + if (System.currentTimeMillis() - lastOnMoveCall > 250){ + send = true; + lastOnMoveCall = System.currentTimeMillis(); + } + String telegram = ""; + homeViewModel.setText(Integer.toString(angle), Integer.toString(strength)); //8 segments of the joystick if((angle >= 338 || angle < 22) && strength != 0){ joystick.setBackgroundResource(R.mipmap.right); - com.sendData(com.telegram(new int[]{1, -1, -1, 1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{1, -1, -1, 1}, strength); }else if((angle >= 22 && angle < 67) && strength != 0){ joystick.setBackgroundResource(R.mipmap.right_forward); - com.sendData(com.telegram(new int[]{1, 0, 0, 1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{1, 0, 0, 1}, strength); }else if((angle >=67 && angle < 112) && strength != 0){ joystick.setBackgroundResource(R.mipmap.forward); - com.sendData(com.telegram(new int[]{1, 1, 1, 1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{1, 1, 1, 1}, strength); }else if((angle >=112 && angle < 157) && strength != 0){ joystick.setBackgroundResource(R.mipmap.left_forward); - com.sendData(com.telegram(new int[]{0, 1, 1, 0}, strength), ipAddress, port); + telegram = com.telegram(new int[]{0, 1, 1, 0}, strength); }else if((angle >=157 && angle < 202) && strength != 0){ joystick.setBackgroundResource(R.mipmap.left); - com.sendData(com.telegram(new int[]{-1, 1, 1, -1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{-1, 1, 1, -1}, strength); }else if((angle >=202 && angle < 247) && strength != 0){ joystick.setBackgroundResource(R.mipmap.left_back); - com.sendData(com.telegram(new int[]{-1, 0, 0, -1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{-1, 0, 0, -1}, strength); }else if((angle >=247 && angle < 292) && strength != 0){ joystick.setBackgroundResource(R.mipmap.back); - com.sendData(com.telegram(new int[]{-1, -1, -1, -1}, strength), ipAddress, port); + telegram = com.telegram(new int[]{-1, -1, -1, -1}, strength); }else if((angle >=292 && angle < 337) && strength != 0){ joystick.setBackgroundResource(R.mipmap.right_back); - com.sendData(com.telegram(new int[]{0, -1, -1, 0}, strength), ipAddress, port); + telegram = com.telegram(new int[]{0, -1, -1, 0}, strength); } else{ joystick.setBackgroundResource(R.mipmap.blank); - com.sendData(com.telegram(new int[]{0, 0, 0, 0}, strength), ipAddress, port); + telegram = com.telegram(new int[]{0, 0, 0, 0}, strength); + } + if (send && mainActivity.connected) + { + mainActivity.sendTelegram(telegram); + // Log.v("TAG", telegram + "\n"); } } }); @@ -112,6 +172,7 @@ public class HomeFragment extends Fragment { @Override public void onDestroyView() { super.onDestroyView(); + // dataTransferAsyncTask.cancel(false); binding = null; } } diff --git a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java index 8c5a9fe..9ddd199 100644 --- a/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java +++ b/MobileApp/app/src/main/java/com/example/lfrmobileapp/ui/notifications/NotificationsFragment.java @@ -1,6 +1,5 @@ package com.example.lfrmobileapp.ui.notifications; -import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; @@ -8,7 +7,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; -import android.widget.TextView; import android.widget.Toast; import androidx.annotation.NonNull; @@ -16,24 +14,65 @@ import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; import com.example.lfrmobileapp.Communication; -import com.example.lfrmobileapp.R; +import com.example.lfrmobileapp.DataTransferAsyncTask; +import com.example.lfrmobileapp.MainActivity; import com.example.lfrmobileapp.databinding.FragmentEinstellungenBinding; +import java.io.DataOutputStream; +import java.net.Socket; + + +/*class NetworkThread extends Thread { + String ip; + int port; + boolean connected; + + NetworkThread(String ip, int port) { + this.ip = ip; + this.port = port; + this.connected = false; + } + + public void run() { + try { + Socket socket = new Socket(ip, port); + DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream()); + outputStream.writeBytes("Verbindung aufbauen"); + outputStream.flush(); + socket.close(); + connected = true; + + } catch (Exception e) { + e.printStackTrace(); + connected = false; + } + } +}*/ public class NotificationsFragment extends Fragment { + Boolean connected = false; + MainActivity mainActivity; + String ipKey = "ipkey"; String portKey = "portkey"; String connectionFailed = "Verbindung fehlgeschlagen."; String connectionSuccessful = "Verbindung erfolgreich."; - String ipAddress = "192.168.0.1"; - int port = 8000; + String ipAddress = "192.168.4.1"; + int port = 8080; int duration = Toast.LENGTH_LONG; + DataTransferAsyncTask dataTransferAsyncTask; private FragmentEinstellungenBinding binding; + @Override + public void onAttach(Context context) { + super.onAttach(context); + mainActivity = (MainActivity) context; + } + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { NotificationsViewModel notificationsViewModel = @@ -56,13 +95,21 @@ public class NotificationsFragment extends Fragment { binding.port.setText(""); } + // dataTransferAsyncTask = new DataTransferAsyncTask(ipAddress, port); final Button button = binding.connect; button.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { - ipAddress = String.valueOf(binding.ipAdress.getText()); - port = Integer.parseInt(String.valueOf(binding.port.getText())); - if(com.sendData("", ipAddress, port)){ + try { + ipAddress = String.valueOf(binding.ipAdress.getText()); + port = Integer.parseInt(String.valueOf(binding.port.getText())); + } catch (Exception e){ + System.err.println("Parse Exception: " + e.getMessage()); + } + + connected = mainActivity.connectToWifi(ipAddress, port); + + if(connected){ editor.putString(ipKey, ipAddress); editor.putInt(portKey, port); editor.apply(); @@ -71,17 +118,18 @@ public class NotificationsFragment extends Fragment { }else{ Toast toast = Toast.makeText(v.getContext(), connectionFailed, duration); toast.show(); + // dataTransferAsyncTask.cancel(true); } } }); - return root; } @Override public void onDestroyView() { super.onDestroyView(); + // dataTransferAsyncTask.cancel(true); binding = null; } } \ No newline at end of file diff --git a/MobileApp/app/src/main/res/layout/fragment_automatik.xml b/MobileApp/app/src/main/res/layout/fragment_automatik.xml index dd1c3cc..e6065ed 100644 --- a/MobileApp/app/src/main/res/layout/fragment_automatik.xml +++ b/MobileApp/app/src/main/res/layout/fragment_automatik.xml @@ -85,7 +85,7 @@