├── .idea
├── .name
├── copyright
│ └── profiles_settings.xml
├── scopes
│ └── scope_settings.xml
├── encodings.xml
├── vcs.xml
├── libraries
│ ├── android_support_v4.xml
│ ├── android_support_v42.xml
│ ├── android_support_v4_21140bf6fab9e46a2078cb37c22ba41c.xml
│ └── android_support_v4_21140bf6fab9e46a2078cb37c22ba41c2.xml
├── modules.xml
├── compiler.xml
└── misc.xml
├── MultiwiiRemote
├── ic_launcher-web.png
├── libs
│ └── android-support-v4.jar
├── res
│ ├── drawable-hdpi
│ │ ├── ic_launcher.png
│ │ ├── mwdragon_background.png
│ │ └── progressbar_color.xml
│ ├── drawable-mdpi
│ │ ├── ic_launcher.png
│ │ └── mwdragon_background.png
│ ├── drawable-xhdpi
│ │ ├── ic_launcher.png
│ │ └── mwdragon_background.png
│ ├── drawable-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── mwdragon_background.png
│ ├── drawable-ldpi
│ │ └── mwdragon_background.png
│ ├── values-sw600dp
│ │ └── dimens.xml
│ ├── values
│ │ ├── dimens.xml
│ │ ├── styles.xml
│ │ ├── arrays.xml
│ │ └── strings.xml
│ ├── menu
│ │ └── main.xml
│ ├── values-sw720dp-land
│ │ └── dimens.xml
│ ├── layout
│ │ ├── device_name.xml
│ │ ├── device_list.xml
│ │ └── activity_main.xml
│ └── xml
│ │ └── preferences.xml
├── src
│ ├── com
│ │ └── multiwii
│ │ │ ├── communication
│ │ │ ├── CommunicationMode.java
│ │ │ ├── Communication.java
│ │ │ ├── Wifi.java
│ │ │ ├── Bluetooth.java
│ │ │ └── DeviceListActivity.java
│ │ │ ├── multiwiiremote
│ │ │ ├── RepeatTimer.java
│ │ │ ├── MainActivityCommunicationHandler.java
│ │ │ ├── MainActivityEvents.java
│ │ │ ├── Settings.java
│ │ │ ├── BaseActivity.java
│ │ │ ├── RCSignals.java
│ │ │ ├── App.java
│ │ │ └── MainActivity.java
│ │ │ ├── Utilities
│ │ │ ├── Camera.java
│ │ │ ├── LowPassFilter.java
│ │ │ ├── SoundManager.java
│ │ │ ├── VarioSoundClass.java
│ │ │ ├── TTS.java
│ │ │ ├── Utilities.java
│ │ │ └── Sensors.java
│ │ │ └── protocol
│ │ │ └── FileAccess.java
│ └── view
│ │ ├── joystick
│ │ ├── JoystickClickedListener.java
│ │ ├── JoystickMovedListener.java
│ │ ├── DualJoystickView.java
│ │ └── JoystickView.java
│ │ ├── VerticalProgressBar.java
│ │ └── mjpeg
│ │ ├── MjpegInputStream.java
│ │ └── MjpegView.java
├── gen
│ └── com
│ │ └── multiwii
│ │ └── multiwiiremote
│ │ ├── Manifest.java
│ │ ├── BuildConfig.java
│ │ └── R.java
├── project.properties
├── MultiwiiRemote.iml
├── proguard-project.txt
└── AndroidManifest.xml
├── out
└── production
│ └── MultiwiiRemote
│ ├── MultiwiiRemote.apk
│ ├── view
│ ├── mjpeg
│ │ ├── MjpegView.class
│ │ ├── MjpegInputStream.class
│ │ └── MjpegView$MjpegViewThread.class
│ ├── VerticalProgressBar.class
│ └── joystick
│ │ ├── JoystickView.class
│ │ ├── JoystickView$1.class
│ │ ├── JoystickView$2.class
│ │ ├── DualJoystickView.class
│ │ ├── JoystickMovedListener.class
│ │ └── JoystickClickedListener.class
│ └── com
│ └── multiwii
│ ├── Utilities
│ ├── TTS.class
│ ├── Camera.class
│ ├── Sensors.class
│ ├── Sensors$1.class
│ ├── Utilities.class
│ ├── LowPassFilter.class
│ ├── SoundManager.class
│ ├── Utilities$1.class
│ ├── Utilities$2.class
│ ├── Utilities$3.class
│ ├── VarioSoundClass.class
│ ├── VarioSoundClass$1.class
│ ├── Sensors$GPSListener.class
│ └── Sensors$MagAccListener.class
│ ├── communication
│ ├── Wifi.class
│ ├── Bluetooth.class
│ ├── Communication.class
│ ├── CommunicationMode.class
│ ├── DeviceListActivity.class
│ ├── DeviceListActivity$1.class
│ ├── DeviceListActivity$2.class
│ └── DeviceListActivity$3.class
│ ├── multiwiiremote
│ ├── App.class
│ ├── R.class
│ ├── App$1.class
│ ├── R$id.class
│ ├── R$xml.class
│ ├── R$array.class
│ ├── R$attr.class
│ ├── R$dimen.class
│ ├── R$layout.class
│ ├── R$menu.class
│ ├── R$string.class
│ ├── R$style.class
│ ├── Settings.class
│ ├── R$drawable.class
│ ├── RCSignals.class
│ ├── Settings$1.class
│ ├── Settings$2.class
│ ├── BaseActivity.class
│ ├── BuildConfig.class
│ ├── MainActivity.class
│ ├── RCSignals$1.class
│ ├── RepeatTimer.class
│ ├── MainActivity$1.class
│ ├── MainActivityEvents.class
│ ├── MainActivityEvents$1.class
│ ├── MainActivityEvents$2.class
│ ├── MainActivityEvents$3.class
│ ├── MainActivityEvents$4.class
│ ├── RCSignals$AdjustMode.class
│ ├── App$SettingsConstants.class
│ ├── MainActivity$InputMode.class
│ ├── BaseActivity$UpdateThread.class
│ ├── MainActivityCommunicationHandler.class
│ └── MainActivityCommunicationHandler$1.class
│ └── protocol
│ ├── FileAccess.class
│ ├── MultiWii230.class
│ ├── MultirotorData.class
│ ├── MultirotorData$ConnectThread.class
│ └── MultirotorData$ConnectedThread.class
├── README.md
├── .gitattributes
├── .gitignore
└── LICENSE
/.idea/.name:
--------------------------------------------------------------------------------
1 | Multiwii-Remote
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/MultiwiiRemote/ic_launcher-web.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/ic_launcher-web.png
--------------------------------------------------------------------------------
/MultiwiiRemote/libs/android-support-v4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/libs/android-support-v4.jar
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/MultiwiiRemote.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/MultiwiiRemote.apk
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-hdpi/mwdragon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-hdpi/mwdragon_background.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-ldpi/mwdragon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-ldpi/mwdragon_background.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-mdpi/mwdragon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-mdpi/mwdragon_background.png
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-xhdpi/mwdragon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-xhdpi/mwdragon_background.png
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/communication/CommunicationMode.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.communication;
2 |
3 | public enum CommunicationMode {
4 | BLUETOOTH, WIFI;
5 | }
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/mjpeg/MjpegView.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/mjpeg/MjpegView.class
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-xxhdpi/mwdragon_background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/MultiwiiRemote/res/drawable-xxhdpi/mwdragon_background.png
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/TTS.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/TTS.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/VerticalProgressBar.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/VerticalProgressBar.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/JoystickView.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/JoystickView.class
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DEPRECATED
2 |
3 | ## Multiwii-Remote
4 |
5 | A free android app for controlling a multiwii copter.
6 |
7 | More info: http://www.multiwii.com/forum/viewtopic.php?f=8&t=4594
8 |
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/JoystickView$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/JoystickView$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/JoystickView$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/JoystickView$2.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/mjpeg/MjpegInputStream.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/mjpeg/MjpegInputStream.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Camera.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Camera.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/Wifi.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/Wifi.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/DualJoystickView.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/DualJoystickView.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$id.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$id.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$xml.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$xml.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/protocol/FileAccess.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/protocol/FileAccess.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/protocol/MultiWii230.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/protocol/MultiWii230.class
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/LowPassFilter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/LowPassFilter.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/SoundManager.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/SoundManager.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$2.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Utilities$3.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/Bluetooth.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/Bluetooth.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$array.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$array.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$attr.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$attr.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$dimen.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$dimen.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$layout.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$layout.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$menu.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$menu.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$string.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$string.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$style.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$style.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/JoystickMovedListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/JoystickMovedListener.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/mjpeg/MjpegView$MjpegViewThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/mjpeg/MjpegView$MjpegViewThread.class
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/joystick/JoystickClickedListener.java:
--------------------------------------------------------------------------------
1 | package view.joystick;
2 |
3 | public interface JoystickClickedListener {
4 | public void OnClicked();
5 | public void OnReleased();
6 | }
7 |
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/VarioSoundClass.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/VarioSoundClass.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$drawable.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/R$drawable.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/Settings$2.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/view/joystick/JoystickClickedListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/view/joystick/JoystickClickedListener.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/VarioSoundClass$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/VarioSoundClass$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/Communication.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/Communication.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BaseActivity.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BaseActivity.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BuildConfig.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BuildConfig.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RepeatTimer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RepeatTimer.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$GPSListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$GPSListener.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$MagAccListener.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/Utilities/Sensors$MagAccListener.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/CommunicationMode.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/CommunicationMode.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$2.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/communication/DeviceListActivity$3.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$1.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$2.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$3.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$4.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityEvents$4.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals$AdjustMode.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/RCSignals$AdjustMode.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App$SettingsConstants.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/App$SettingsConstants.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity$InputMode.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivity$InputMode.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData$ConnectThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData$ConnectThread.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BaseActivity$UpdateThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/BaseActivity$UpdateThread.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData$ConnectedThread.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/protocol/MultirotorData$ConnectedThread.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityCommunicationHandler.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityCommunicationHandler.class
--------------------------------------------------------------------------------
/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityCommunicationHandler$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bug-assassin/Multiwii-Remote/HEAD/out/production/MultiwiiRemote/com/multiwii/multiwiiremote/MainActivityCommunicationHandler$1.class
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values-sw600dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/joystick/JoystickMovedListener.java:
--------------------------------------------------------------------------------
1 | package view.joystick;
2 |
3 | public interface JoystickMovedListener {
4 | public void OnMoved(int pan, int tilt);
5 | public void OnReleased();
6 | public void OnReturnedToCenter();
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 16dp
5 | 16dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/MultiwiiRemote/gen/com/multiwii/multiwiiremote/Manifest.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.multiwii.multiwiiremote;
4 |
5 | /* This stub is only used by the IDE. It is NOT the Manifest class actually packed into the APK */
6 | public final class Manifest {
7 | }
--------------------------------------------------------------------------------
/.idea/libraries/android_support_v4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/libraries/android_support_v42.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MultiwiiRemote/gen/com/multiwii/multiwiiremote/BuildConfig.java:
--------------------------------------------------------------------------------
1 | /*___Generated_by_IDEA___*/
2 |
3 | package com.multiwii.multiwiiremote;
4 |
5 | /* This stub is only used by the IDE. It is NOT the BuildConfig class actually packed into the APK */
6 | public final class BuildConfig {
7 | public final static boolean DEBUG = Boolean.parseBoolean(null);
8 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values-sw720dp-land/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 | 128dp
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/libraries/android_support_v4_21140bf6fab9e46a2078cb37c22ba41c.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/libraries/android_support_v4_21140bf6fab9e46a2078cb37c22ba41c2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 | *.sln merge=union
7 | *.csproj merge=union
8 | *.vbproj merge=union
9 | *.fsproj merge=union
10 | *.dbproj merge=union
11 |
12 | # Standard to msysgit
13 | *.doc diff=astextplain
14 | *.DOC diff=astextplain
15 | *.docx diff=astextplain
16 | *.DOCX diff=astextplain
17 | *.dot diff=astextplain
18 | *.DOT diff=astextplain
19 | *.pdf diff=astextplain
20 | *.PDF diff=astextplain
21 | *.rtf diff=astextplain
22 | *.RTF diff=astextplain
23 |
--------------------------------------------------------------------------------
/MultiwiiRemote/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-21
15 |
16 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/RepeatTimer.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 |
4 | public class RepeatTimer {
5 | long lastMillis = 0;
6 | int millisBetween = 0;
7 |
8 | public RepeatTimer(int millisBetween) {
9 | setMillisBetween(millisBetween);
10 | }
11 | public void setMillisBetween(int millisBetween) {
12 | this.millisBetween = millisBetween;
13 | }
14 | public boolean isTime() {
15 | return System.currentTimeMillis() > lastMillis + millisBetween;
16 | }
17 | public void reset() {
18 | lastMillis = getCurrentTime();
19 | }
20 | private long getCurrentTime() {
21 | return System.currentTimeMillis();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/Camera.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | import com.multiwii.multiwiiremote.App;
4 |
5 | import android.app.Activity;
6 | import view.mjpeg.MjpegInputStream;
7 | import view.mjpeg.MjpegView;
8 |
9 | public class Camera {
10 | private MjpegView mv;
11 | private Activity mActivity;
12 |
13 | public Camera(MjpegView mv, Activity mActivity) {
14 | this.mv = mv;
15 | this.mActivity = mActivity;
16 | }
17 |
18 | public void start() {
19 | String URL = "http://" + ((App) mActivity.getApplication()).IpAddress
20 | + ":8080/?action=stream";
21 | mv.setSource(MjpegInputStream.read(URL));
22 | mv.setDisplayMode(MjpegView.SIZE_BEST_FIT);
23 | }
24 |
25 | public void stop() {
26 | mv.stopPlayback();
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/MultiwiiRemote/MultiwiiRemote.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
14 |
15 |
16 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/MultiwiiRemote/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - 100
5 | - 150
6 | - 200
7 | - 250
8 | - 300
9 | - 350
10 | - 400
11 | - 450
12 | - 500
13 |
14 |
15 | - Bluetooth
16 | - Wifi
17 |
18 |
19 |
20 | - Connect
21 | - Toggle Accel
22 | - Settings
23 |
24 |
25 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/layout/device_name.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/LowPassFilter.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | public class LowPassFilter {
4 | /*
5 | * time smoothing constant for low-pass filter 0 ≤ alpha ≤ 1 ; a smaller
6 | * value basically means more smoothing See: http://en.wikipedia.org/wiki
7 | * /Low-pass_filter#Discrete-time_realization
8 | */
9 | float ALPHA = 0f;
10 | float lastOutput = 0;
11 | public LowPassFilter(float ALPHA) {
12 | this.ALPHA = ALPHA;
13 | }
14 |
15 | public float lowPass(float input) {//rad
16 | if (Math.abs(input - lastOutput) > 0.9 * Math.PI) {
17 | lastOutput = input;
18 | return lastOutput;
19 | }
20 | lastOutput = lastOutput + ALPHA * (input - lastOutput);
21 | return lastOutput;
22 | }
23 |
24 | public int lowPass(int input) {//degree
25 | if (Math.abs(input - lastOutput) > 170) {
26 | lastOutput = input;
27 | return (int)lastOutput;
28 | }
29 | lastOutput = lastOutput + ALPHA * (input - lastOutput);
30 | return (int)lastOutput;
31 | }
32 | public void setFilter(float ALPHA) {
33 | this.ALPHA = ALPHA;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/SoundManager.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | import java.util.HashMap;
4 |
5 | import android.content.Context;
6 | import android.media.AudioManager;
7 | import android.media.SoundPool;
8 |
9 | public class SoundManager {
10 |
11 | private SoundPool mSoundPool;
12 | private HashMap mSoundPoolMap;
13 | private AudioManager mAudioManager;
14 | private Context mContext;
15 |
16 | public SoundManager(Context theContext) {
17 | mContext = theContext;
18 | mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
19 | mSoundPoolMap = new HashMap();
20 | mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
21 | }
22 |
23 | public void addSound(int Index, int SoundID) {
24 | mSoundPoolMap.put(Index, mSoundPool.load(mContext, SoundID, 1));
25 | }
26 |
27 | public void playSound(int index) {
28 |
29 | int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
30 | mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, 0, 1f);
31 | }
32 |
33 | public void playLoopedSound(int index) {
34 |
35 | int streamVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
36 | mSoundPool.play(mSoundPoolMap.get(index), streamVolume, streamVolume, 1, -1, 1f);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Multiwii Remote
5 | Settings
6 | AUX1
7 | AUX2
8 | AUX3
9 | AUX4
10 | Status
11 |
12 |
13 | scanning for devices
14 | select a device to connect
15 | No devices have been paired
16 | No devices found
17 | Paired Devices
18 | Other Available Devices
19 | Scan for devices
20 | Mode
21 | Menu
22 |
25 | Signal Strength
26 | Phone Heading
27 |
28 |
29 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/MainActivityCommunicationHandler.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 | import java.lang.ref.WeakReference;
4 |
5 | import com.multiwii.Utilities.Utilities;
6 | import com.multiwii.communication.Communication;
7 | import com.multiwii.communication.CommunicationMode;
8 |
9 | import android.os.CountDownTimer;
10 | import android.os.Handler;
11 | import android.os.Message;
12 | import android.util.Log;
13 |
14 | public class MainActivityCommunicationHandler extends Handler {
15 | private final WeakReference mActivity;
16 |
17 | public MainActivityCommunicationHandler(MainActivity activity) {
18 | mActivity = new WeakReference(activity);
19 | }
20 | @Override
21 | public void handleMessage(Message msg) {
22 | final MainActivity myNewActivity = mActivity.get();
23 | if(myNewActivity != null)
24 | switch (msg.what) {
25 | case Communication.MESSAGE_STATE_CHANGE:
26 | switch (msg.arg1) {
27 | case Communication.STATE_CONNECTED:
28 | myNewActivity.setStatus("Connected");
29 | if(myNewActivity.app.comMode == CommunicationMode.WIFI)
30 | new CountDownTimer(5000, 10) {
31 | public void onTick(long millisUntilFinished ) {
32 | myNewActivity.setStatus(millisUntilFinished + "");
33 | }
34 | public void onFinish() {
35 | /*if(myNewActivity.isCamera)
36 | myNewActivity.startWebCam();*/
37 | myNewActivity.setStatus("Connected");
38 | }
39 | }.start();
40 | break;
41 | }
42 | break;
43 | case App.SENSORSCHANGED:
44 | myNewActivity.onSensorsStateChangeRotate();
45 | break;
46 | case Communication.MESSAGE_TOAST:
47 | Utilities.showToast(msg.getData().getString(Communication.TOAST), myNewActivity);
48 | break;
49 | case 7: //Update UI
50 | myNewActivity.UpdateUI();
51 | break;
52 | }
53 | }
54 |
55 | };
56 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/drawable-hdpi/progressbar_color.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 |
14 |
21 |
22 |
23 |
24 | -
25 |
26 |
27 |
28 |
35 |
36 |
37 |
38 |
39 | -
40 |
41 |
42 |
43 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/VarioSoundClass.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | import android.media.AudioFormat;
4 | import android.media.AudioManager;
5 | import android.media.AudioTrack;
6 |
7 | public class VarioSoundClass {
8 |
9 | boolean m_stop = false;
10 | AudioTrack m_audioTrack;
11 | Thread m_playSoundThread;
12 |
13 | private final int sampleRate = 8000;
14 | private final int numSamples = AudioTrack.getMinBufferSize(sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT);
15 | private final double sample[] = new double[numSamples];
16 | private double freqOfTone = 1000; // hz
17 |
18 | private final byte generatedSnd[] = new byte[2 * numSamples];
19 |
20 | Runnable m_noiseGenerator = new Runnable() {
21 | public void run() {
22 | // while (!m_stop) {
23 | Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
24 |
25 | for (int i = 0; i < numSamples; ++i) {
26 | sample[i] = Math.sin(2 * Math.PI * i / (sampleRate / freqOfTone));
27 | }
28 |
29 | // convert to 16 bit pcm sound array
30 | // assumes the sample buffer is normalised.
31 | int idx = 0;
32 | for (final double dVal : sample) {
33 | // scale to maximum amplitude
34 | final short val = (short) ((dVal * 32767));
35 | // in 16 bit wav PCM, first byte is the low order byte
36 | generatedSnd[idx++] = (byte) (val & 0x00ff);
37 | generatedSnd[idx++] = (byte) ((val & 0xff00) >>> 8);
38 |
39 | }
40 |
41 | m_audioTrack.write(generatedSnd, 0, generatedSnd.length);
42 | m_audioTrack.play();
43 |
44 | try {
45 | Thread.sleep(900);
46 | } catch (InterruptedException e) {
47 | // TODO Auto-generated catch block
48 | e.printStackTrace();
49 | }
50 | // }
51 | }
52 | };
53 |
54 | public void Play(double frequency) {
55 | freqOfTone = frequency;
56 |
57 | m_stop = false;
58 | m_audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate, AudioFormat.CHANNEL_OUT_MONO, AudioFormat.ENCODING_PCM_16BIT, generatedSnd.length, AudioTrack.MODE_STREAM);
59 |
60 | // m_audioTrack.play();
61 |
62 | m_playSoundThread = new Thread(m_noiseGenerator);
63 | m_playSoundThread.start();
64 | }
65 |
66 | void stop() {
67 | m_stop = true;
68 | m_audioTrack.stop();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/TTS.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | import java.util.Locale;
4 |
5 | import android.content.Context;
6 | import android.speech.tts.TextToSpeech;
7 | import android.util.Log;
8 |
9 | public class TTS implements TextToSpeech.OnInitListener {
10 | private TextToSpeech tts;
11 | public static final int TTS_CHECK_CODE = 2345;
12 | Context context;
13 | public boolean TTSinit = false;
14 | boolean inicjalizacja = false;
15 | String tag = "smsreader";
16 | String text;
17 |
18 | private void CreateTTS() {
19 | Log.d(tag, "CreateTTS");
20 |
21 | if (!inicjalizacja) {
22 |
23 | tts = new TextToSpeech(context, this);
24 |
25 | inicjalizacja = true;
26 |
27 | }
28 | }
29 |
30 | public TTS(Context context) {
31 | this.context = context;
32 | Log.d(tag, "text to speach init TTSinit " + String.valueOf(TTSinit));
33 | }
34 |
35 | @Override
36 | public void onInit(int status) {
37 | if (status == TextToSpeech.SUCCESS) {
38 |
39 | int result = tts.setLanguage(Locale.ENGLISH);
40 | Log.d("aaa", Locale.getDefault().getLanguage());
41 | if (Locale.getDefault().getLanguage().equals("de")) {
42 | result = tts.setLanguage(Locale.getDefault());
43 | Log.d("aaa", "german");
44 | }
45 |
46 | if (Locale.getDefault().getLanguage().equals("hu")) {
47 | result = tts.setLanguage(Locale.getDefault());
48 | Log.d("aaa", "hungarian");
49 | }
50 |
51 | if (Locale.getDefault().getLanguage().equals("pl")) {
52 | result = tts.setLanguage(Locale.getDefault());
53 | Log.d("aaa", "polish");
54 | }
55 |
56 | if (result == TextToSpeech.LANG_MISSING_DATA
57 | || result == TextToSpeech.LANG_NOT_SUPPORTED) {
58 | Log.e("TTS", "This Language is not supported");
59 | }
60 |
61 | TTSinit = true;
62 | tts.speak(this.text, TextToSpeech.QUEUE_ADD, null);
63 |
64 | } else {
65 | TTSinit = false;
66 | }
67 |
68 | Log.d(tag, "text to speach init status " + String.valueOf(status));
69 | Log.d(tag, "text to speach init TTSinit " + String.valueOf(TTSinit));
70 | }
71 |
72 | public void Speak(String text) {
73 |
74 | Log.d(tag, "Speak:" + text);
75 | if (TTSinit) {
76 |
77 | tts.speak(text, TextToSpeech.QUEUE_ADD, null);
78 | } else {
79 | this.text = text;
80 | CreateTTS();
81 | }
82 |
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/layout/device_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
21 |
30 |
36 |
45 |
51 |
56 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/MainActivityEvents.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 | import android.util.Log;
4 | import android.view.View;
5 | import android.view.View.OnClickListener;
6 | import android.widget.CompoundButton;
7 | import android.widget.CompoundButton.OnCheckedChangeListener;
8 | import view.joystick.JoystickMovedListener;
9 |
10 | public class MainActivityEvents {
11 | private MainActivity mActivity;
12 |
13 | public MainActivityEvents(MainActivity mActivity) {
14 | this.mActivity = mActivity;
15 | }
16 | public JoystickMovedListener _throttleListener = new JoystickMovedListener() {
17 | @Override
18 | public void OnMoved(int delta_yaw, int delta_throttle) {
19 | delta_yaw = delta_yaw / 10; //reduce yaw range. -50~50 SONG BO
20 | mActivity.rc.setAdjustedYaw(delta_yaw);
21 | mActivity.rc.setAdjustedThrottle(-delta_throttle);
22 | }
23 |
24 | @Override
25 | public void OnReleased() {
26 |
27 | }
28 |
29 | @Override
30 | public void OnReturnedToCenter() {
31 |
32 | }
33 | };
34 | public JoystickMovedListener _listener = new JoystickMovedListener() {
35 | @Override
36 | public void OnMoved(int pan, int tilt) {
37 | mActivity.rc.setAdjustedRoll(pan);
38 | mActivity.rc.setAdjustedPitch(-tilt);
39 | }
40 |
41 | @Override
42 | public void OnReleased() {
43 |
44 | }
45 |
46 | public void OnReturnedToCenter() {
47 | mActivity.rc.setMid(new byte[] { RCSignals.ROLL, RCSignals.PITCH });
48 | };
49 | };
50 |
51 | public OnClickListener mClickListener = new OnClickListener() {
52 | @Override
53 | public void onClick(View v) {
54 | switch (v.getId()) {
55 | case R.id.aux1Btn:
56 | mActivity.aux1_Click(v);
57 | break;
58 | case R.id.aux2Btn:
59 | mActivity.aux2_Click(v);
60 | break;
61 | case R.id.aux3Btn:
62 | mActivity.aux3_Click(v);
63 | break;
64 | case R.id.aux4Btn:
65 | mActivity.aux4_Click(v);
66 | break;
67 | case R.id.switchModes:
68 | mActivity.rc.switchMode();
69 | break;
70 | }
71 | }
72 | };
73 | public OnCheckedChangeListener mCheckChangeListener = new OnCheckedChangeListener() {
74 | @Override
75 | public void onCheckedChanged(CompoundButton arg0, boolean state) {
76 | // TODO Auto-generated method stub
77 | if(state == true){
78 | mActivity.app.sensors.start();
79 | }
80 | else{
81 | mActivity.app.sensors.stop();
82 | }
83 | }
84 | };
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/VerticalProgressBar.java:
--------------------------------------------------------------------------------
1 | package view;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.util.AttributeSet;
6 | import android.view.MotionEvent;
7 | import android.widget.ProgressBar;
8 |
9 | public class VerticalProgressBar extends ProgressBar {
10 | private int x, y, z, w;
11 |
12 | @Override
13 | protected void drawableStateChanged() {
14 | // TODO Auto-generated method stub
15 | super.drawableStateChanged();
16 | }
17 |
18 | public VerticalProgressBar(Context context) {
19 | super(context);
20 | }
21 |
22 | public VerticalProgressBar(Context context, AttributeSet attrs, int defStyle) {
23 | super(context, attrs, defStyle);
24 | }
25 |
26 | public VerticalProgressBar(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | }
29 |
30 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
31 | super.onSizeChanged(h, w, oldh, oldw);
32 | this.x = w;
33 | this.y = h;
34 | this.z = oldw;
35 | this.w = oldh;
36 | }
37 |
38 | @Override
39 | protected synchronized void onMeasure(int widthMeasureSpec,
40 | int heightMeasureSpec) {
41 | super.onMeasure(heightMeasureSpec, widthMeasureSpec);
42 | setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
43 | }
44 |
45 | protected void onDraw(Canvas c) {
46 | c.rotate(-90);
47 | c.translate(-getHeight(), 0);
48 | super.onDraw(c);
49 | }
50 |
51 | @Override
52 | public boolean onTouchEvent(MotionEvent event) {
53 | if (!isEnabled()) {
54 | return false;
55 | }
56 |
57 | switch (event.getAction()) {
58 | case MotionEvent.ACTION_DOWN:
59 |
60 | setSelected(true);
61 | setPressed(true);
62 | break;
63 | case MotionEvent.ACTION_MOVE:
64 | setProgress(getMax()
65 | - (int) (getMax() * event.getY() / getHeight()));
66 | onSizeChanged(getWidth(), getHeight(), 0, 0);
67 |
68 | break;
69 | case MotionEvent.ACTION_UP:
70 | setSelected(false);
71 | setPressed(false);
72 | break;
73 |
74 | case MotionEvent.ACTION_CANCEL:
75 | break;
76 | }
77 | return true;
78 | }
79 |
80 | @Override
81 | public synchronized void setProgress(int progress) {
82 |
83 | if (progress >= 0)
84 | super.setProgress(progress);
85 |
86 | else
87 | super.setProgress(0);
88 | onSizeChanged(x, y, z, w);
89 |
90 | }
91 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | "
32 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
47 |
48 |
49 |
50 |
51 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/Settings.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 | import java.util.regex.Pattern;
4 |
5 | import com.multiwii.Utilities.Utilities;
6 | import com.multiwii.multiwiiremote.App.SettingsConstants;
7 |
8 | import android.app.Activity;
9 | import android.os.Bundle;
10 | import android.preference.Preference;
11 | import android.preference.PreferenceActivity;
12 |
13 |
14 | public class Settings extends PreferenceActivity {
15 |
16 | private Preference[] mPreferenceEntries;
17 | private Activity currentActivity;
18 | private static final String IPADDRESS_PATTERN =
19 | "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
20 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
21 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
22 | "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
23 |
24 | @SuppressWarnings("deprecation")
25 | @Override
26 | public void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | addPreferencesFromResource(R.xml.preferences);
29 | currentActivity = this;
30 | SettingsConstants[] myConst = SettingsConstants.values();
31 | mPreferenceEntries = new Preference[myConst.length];
32 |
33 | for (int i = 0; i < myConst.length; i++) {
34 | mPreferenceEntries[i] = this.getPreferenceScreen().findPreference(myConst[i].toString().trim());
35 | mPreferenceEntries[i].setOnPreferenceChangeListener(changeListener);
36 | }
37 | }
38 | protected void onPause() {
39 | super.onPause();
40 | ((App) getApplication()).ReadSettings();
41 | }
42 |
43 | Preference.OnPreferenceChangeListener changeListener = new Preference.OnPreferenceChangeListener() {
44 | public boolean onPreferenceChange(Preference preference, Object newValue) {
45 | boolean result = validate(preference, newValue);
46 |
47 | if(!result) Utilities.showToast("Invalid value", currentActivity);
48 |
49 | return result;
50 | }
51 | };
52 |
53 | private boolean validate(Preference preference, Object newValue) {
54 | SettingsConstants setting = SettingsConstants.valueOf(preference.getKey());
55 |
56 | switch(setting) {
57 | case IPADDRESS: return isValidIpAddress(newValue);
58 | case BAUDRATE: return isValidBaudRate(newValue);
59 | case TRIMROLL: return isTrimInRange(newValue);
60 | case TRIMPITCH: return isTrimInRange(newValue);
61 | default: return setting.validate(newValue);
62 | }
63 | }
64 | private boolean isValidIpAddress(Object newValue) {
65 | return Pattern.compile(IPADDRESS_PATTERN).matcher(newValue.toString()).matches();
66 | }
67 | private boolean isValidBaudRate(Object newValue) {
68 | return Utilities.IsInteger(newValue); //TODO For now
69 | }
70 | private boolean isTrimInRange(Object newValue) {
71 | if(!Utilities.IsInteger(newValue)) return false;
72 |
73 | int x = Integer.parseInt(newValue.toString());
74 |
75 | return Math.abs(x) < 500; //TODO associate rc_value
76 | }
77 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/BaseActivity.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.util.Log;
6 | import android.view.Menu;
7 | import android.view.WindowManager;
8 |
9 |
10 |
11 | public abstract class BaseActivity extends Activity {
12 | private long lastRefreshTime = 0;
13 | protected App app;
14 | protected Menu menu;
15 | protected UpdateThread mUpdateThread;
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | lastRefreshTime = System.currentTimeMillis();
20 | app = (App) getApplication();
21 | }
22 | protected void StartUpdateThread() {
23 | StopUpdateThread();
24 | mUpdateThread = new UpdateThread(this);
25 | mUpdateThread.start();
26 | }
27 | protected void StopUpdateThread() {
28 | if(mUpdateThread != null) mUpdateThread.cancel(); mUpdateThread = null;
29 | }
30 | public void KeepScreenOn(boolean keepOn) {
31 | if(keepOn)
32 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
33 | else
34 | getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
35 | }
36 | @Override
37 | protected void onResume() {
38 | super.onResume();
39 | app.onResume();
40 | StartUpdateThread();
41 | }
42 | @Override
43 | protected void onPause() {
44 | super.onPause();
45 | StopUpdateThread();
46 | app.onPause();
47 | }
48 | @Override
49 | protected void onStop() {
50 | super.onStop();
51 | }
52 | //UI Update
53 | public abstract void UpdateUI();
54 |
55 | private synchronized void callFrequentTasks() {
56 | FrequentTasks();
57 | }
58 | public abstract void FrequentTasks();
59 |
60 | @Override
61 | public boolean onCreateOptionsMenu(Menu menu) {
62 | this.menu = menu;
63 | getMenuInflater().inflate(R.menu.main, menu);
64 | return true;
65 | }
66 | private class UpdateThread extends Thread {
67 | private final BaseActivity mActivity;
68 | private boolean cancel = false;
69 |
70 | public UpdateThread(BaseActivity mActivity) {
71 | //Log.d(TAG, "create ConnectedThread");
72 | this.mActivity = mActivity;
73 | }
74 |
75 | public void run() {
76 | //Log.i(TAG, "BEGIN mConnectedWriteThread");
77 |
78 | while (!cancel) {
79 |
80 | mActivity.callFrequentTasks();
81 |
82 | if(cancel) break;
83 |
84 | try {
85 | long currentTime = System.currentTimeMillis();
86 | long elapseTime = currentTime - lastRefreshTime;
87 | if(elapseTime < app.RefreshRate){
88 | Thread.sleep(app.RefreshRate - elapseTime);
89 | }
90 | else{
91 | Log.d("WARNING", "too much works in main tread! cost " + elapseTime + "ms per loop.");
92 | }
93 | lastRefreshTime = System.currentTimeMillis();
94 |
95 | } catch (InterruptedException e) {
96 | // TODO Auto-generated catch block
97 | e.printStackTrace();
98 | }
99 |
100 | }
101 | }
102 |
103 | public void cancel() {
104 | cancel = true;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/mjpeg/MjpegInputStream.java:
--------------------------------------------------------------------------------
1 | package view.mjpeg;
2 |
3 |
4 | import java.io.BufferedInputStream;
5 | import java.io.ByteArrayInputStream;
6 | import java.io.DataInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.net.URI;
10 | import java.util.Properties;
11 |
12 | import org.apache.http.HttpResponse;
13 | import org.apache.http.client.ClientProtocolException;
14 | import org.apache.http.client.methods.HttpGet;
15 | import org.apache.http.impl.client.DefaultHttpClient;
16 |
17 | import android.graphics.Bitmap;
18 | import android.graphics.BitmapFactory;
19 |
20 | public class MjpegInputStream extends DataInputStream {
21 | private final byte[] SOI_MARKER = { (byte) 0xFF, (byte) 0xD8 };
22 | private final byte[] EOF_MARKER = { (byte) 0xFF, (byte) 0xD9 };
23 | private final String CONTENT_LENGTH = "Content-Length";
24 | private final static int HEADER_MAX_LENGTH = 100;
25 | private final static int FRAME_MAX_LENGTH = 40000 + HEADER_MAX_LENGTH;
26 | private int mContentLength = -1;
27 |
28 | public static MjpegInputStream read(String url) {
29 | HttpResponse res;
30 | DefaultHttpClient httpclient = new DefaultHttpClient();
31 | try {
32 | res = httpclient.execute(new HttpGet(URI.create(url)));
33 | return new MjpegInputStream(res.getEntity().getContent());
34 | } catch (ClientProtocolException e) {
35 | } catch (IOException e) {}
36 | return null;
37 | }
38 |
39 | public MjpegInputStream(InputStream in) { super(new BufferedInputStream(in, FRAME_MAX_LENGTH)); }
40 |
41 | private int getEndOfSeqeunce(DataInputStream in, byte[] sequence) throws IOException {
42 | int seqIndex = 0;
43 | byte c;
44 | for(int i=0; i < FRAME_MAX_LENGTH; i++) {
45 | c = (byte) in.readUnsignedByte();
46 | if(c == sequence[seqIndex]) {
47 | seqIndex++;
48 | if(seqIndex == sequence.length) return i + 1;
49 | } else seqIndex = 0;
50 | }
51 | return -1;
52 | }
53 |
54 | private int getStartOfSequence(DataInputStream in, byte[] sequence) throws IOException {
55 | int end = getEndOfSeqeunce(in, sequence);
56 | return (end < 0) ? (-1) : (end - sequence.length);
57 | }
58 |
59 | private int parseContentLength(byte[] headerBytes) throws IOException, NumberFormatException {
60 | ByteArrayInputStream headerIn = new ByteArrayInputStream(headerBytes);
61 | Properties props = new Properties();
62 | props.load(headerIn);
63 | return Integer.parseInt(props.getProperty(CONTENT_LENGTH));
64 | }
65 |
66 | public Bitmap readMjpegFrame() throws IOException {
67 | mark(FRAME_MAX_LENGTH);
68 | int headerLen = getStartOfSequence(this, SOI_MARKER);
69 | reset();
70 | byte[] header = new byte[headerLen];
71 | readFully(header);
72 | try {
73 | mContentLength = parseContentLength(header);
74 | } catch (NumberFormatException nfe) {
75 | mContentLength = getEndOfSeqeunce(this, EOF_MARKER);
76 | }
77 | reset();
78 | byte[] frameData = new byte[mContentLength];
79 | skipBytes(headerLen);
80 | readFully(frameData);
81 | return BitmapFactory.decodeStream(new ByteArrayInputStream(frameData));
82 | }
83 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/protocol/FileAccess.java:
--------------------------------------------------------------------------------
1 | /* MultiWii EZ-GUI
2 | Copyright (C) <2012> Bartosz Szczygiel (eziosoft)
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 | package com.multiwii.protocol;
18 |
19 | import java.io.BufferedReader;
20 | import java.io.BufferedWriter;
21 | import java.io.File;
22 | import java.io.FileReader;
23 | import java.io.FileWriter;
24 | import java.io.IOException;
25 |
26 | import android.os.Environment;
27 | import android.util.Log;
28 |
29 | public class FileAccess {
30 |
31 | String fileName;
32 | File file;
33 | File root;
34 | FileWriter filewriter;
35 | BufferedWriter out;
36 |
37 |
38 |
39 | public static String ReadFile(String fileName) {
40 | File sdcard = Environment.getExternalStorageDirectory();
41 |
42 | // Get the text file
43 | File file = new File(sdcard, fileName);
44 |
45 | // Read text from file
46 | StringBuilder text = new StringBuilder();
47 |
48 | try {
49 | BufferedReader br = new BufferedReader(new FileReader(file));
50 | String line;
51 |
52 | while ((line = br.readLine()) != null) {
53 | text.append(line);
54 | text.append('\n');
55 | }
56 | br.close();
57 | } catch (IOException e) {
58 | // You'll need to add proper error handling here
59 | }
60 | // Set the text
61 | return text.toString();
62 | }
63 |
64 | public FileAccess(String fileName) {
65 |
66 | root = Environment.getExternalStorageDirectory();
67 | file = new File(root, fileName);
68 | try {
69 | Log.d("plik", file.toString());
70 | filewriter = new FileWriter(file);
71 | out = new BufferedWriter(filewriter);
72 | Log.d("plik", "fileAccess OK");
73 | } catch (IOException e) {
74 |
75 | Log.d("plik", "fileAccess ERR");
76 | // Toast.makeText(context, "Can't write to file",
77 | // Toast.LENGTH_LONG).show();
78 | }
79 |
80 | }
81 |
82 | public void Append(String s) {
83 |
84 | if (root.canWrite()) {
85 | try {
86 | out.append(s + "\n");
87 | Log.d("plik", "write OK");
88 | } catch (IOException e) {
89 |
90 | Log.d("plik", "fileAccess ERR");
91 | // Toast.makeText(context, "Can't write to file",
92 | // Toast.LENGTH_LONG).show();
93 | }
94 | }
95 |
96 | }
97 |
98 | public void Write(String s) {
99 |
100 | if (root.canWrite()) {
101 | try {
102 | out.write(s + "\n");
103 |
104 | Log.d("plik", "write OK");
105 | } catch (IOException e) {
106 |
107 | Log.d("plik", "fileAccess ERR");
108 | // Toast.makeText(context, "Can't write to file",
109 | // Toast.LENGTH_LONG).show();
110 | }
111 | }
112 | }
113 |
114 | public void closeFile() {
115 | try {
116 | out.close();
117 | Log.d("plik", "close OK");
118 | } catch (IOException e) {
119 |
120 | Log.d("plik", "fileAccess ERR");
121 | // Toast.makeText(context, "Can't close the file",
122 | // Toast.LENGTH_LONG).show();
123 | }
124 | }
125 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/res/xml/preferences.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/Utilities.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.Utilities;
2 |
3 | import android.app.Activity;
4 | import android.media.AudioManager;
5 | import android.media.MediaPlayer;
6 | import android.media.MediaPlayer.OnCompletionListener;
7 | import android.media.RingtoneManager;
8 | import android.net.Uri;
9 | import android.widget.Toast;
10 |
11 | public class Utilities {
12 | public static void playNotification(Activity myActivity) {
13 | Uri defaultRingtoneUri = RingtoneManager
14 | .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
15 | try {
16 | MediaPlayer mediaPlayer = new MediaPlayer();
17 | mediaPlayer.setDataSource(myActivity.getBaseContext(),
18 | defaultRingtoneUri);
19 | mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION);
20 | mediaPlayer.prepare();
21 | mediaPlayer.setOnCompletionListener(new OnCompletionListener() {
22 |
23 | public void onCompletion(MediaPlayer mp) {
24 | mp.release();
25 | }
26 |
27 | });
28 | mediaPlayer.start();
29 |
30 | } catch (Exception e) {
31 | e.printStackTrace();
32 | }
33 | }
34 |
35 | public static void showToast(final String toast,
36 | final Activity myNewActivity) {
37 | myNewActivity.runOnUiThread(new Runnable() {
38 | public void run() {
39 | Toast.makeText(myNewActivity.getBaseContext(), toast,
40 | Toast.LENGTH_SHORT).show();
41 | }
42 | });
43 | }
44 |
45 | public static void showToast(final String toast,
46 | final Activity myNewActivity, final int length) {
47 | myNewActivity.runOnUiThread(new Runnable() {
48 | public void run() {
49 | Toast.makeText(myNewActivity.getBaseContext(), toast,
50 | length).show();
51 | }
52 | });
53 | }
54 |
55 | public static double mapCons(double x, double in_min, double in_max, double out_min, double out_max)
56 | {
57 | return constrain(map(x, in_min, in_max, out_min, out_max), out_min, out_max);
58 | }
59 |
60 | public static float mapCons(float x, float in_min, float in_max, float out_min, float out_max)
61 | {
62 | return constrain(map(x, in_min, in_max, out_min, out_max), out_min, out_max);
63 | }
64 |
65 | public static double map(double x, double in_min, double in_max, double out_min, double out_max)
66 | {
67 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
68 | }
69 |
70 | public static float map(float x, float in_min, float in_max, float out_min, float out_max)
71 | {
72 | return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
73 | }
74 |
75 | public static double constrain(double x, double min, double max)
76 | {
77 | if(x < min)
78 | return min;
79 | else if(x > max)
80 | return max;
81 | else
82 | return x;
83 | }
84 |
85 | public static float constrain(float x, float min, float max)
86 | {
87 | if(x < min)
88 | return min;
89 | else if(x > max)
90 | return max;
91 | else
92 | return x;
93 | }
94 |
95 | public static boolean IsBoolean(Object newValue) {
96 | try {
97 | Boolean.parseBoolean(newValue.toString());
98 | return true;
99 | }
100 | catch(Exception e) {
101 | return false;
102 | }
103 | }
104 |
105 | public static boolean IsInteger(Object newValue) {
106 | try {
107 | Integer.parseInt(newValue.toString());
108 | return true;
109 | }
110 | catch(Exception e) {
111 | return false;
112 | }
113 | }
114 |
115 | public static boolean IsFloat(Object newValue) {
116 | try {
117 | Float.parseFloat(newValue.toString());
118 | return true;
119 | }
120 | catch(Exception e) {
121 | return false;
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #################
2 | ## Eclipse
3 | #################
4 |
5 | *.pydevproject
6 | .project
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .classpath
16 | .settings/
17 | .loadpath
18 |
19 | # External tool builders
20 | .externalToolBuilders/
21 |
22 | # Locally stored "Eclipse launch configurations"
23 | *.launch
24 |
25 | # CDT-specific
26 | .cproject
27 |
28 | # PDT-specific
29 | .buildpath
30 |
31 |
32 | #################
33 | ## Visual Studio
34 | #################
35 |
36 | ## Ignore Visual Studio temporary files, build results, and
37 | ## files generated by popular Visual Studio add-ons.
38 |
39 | # User-specific files
40 | *.suo
41 | *.user
42 | *.sln.docstates
43 |
44 | # Build results
45 |
46 | [Dd]ebug/
47 | [Rr]elease/
48 | x64/
49 | build/
50 | [Bb]in/
51 | [Oo]bj/
52 |
53 | # MSTest test Results
54 | [Tt]est[Rr]esult*/
55 | [Bb]uild[Ll]og.*
56 |
57 | *_i.c
58 | *_p.c
59 | *.ilk
60 | *.meta
61 | *.obj
62 | *.pch
63 | *.pdb
64 | *.pgc
65 | *.pgd
66 | *.rsp
67 | *.sbr
68 | *.tlb
69 | *.tli
70 | *.tlh
71 | *.tmp
72 | *.tmp_proj
73 | *.log
74 | *.vspscc
75 | *.vssscc
76 | .builds
77 | *.pidb
78 | *.log
79 | *.scc
80 |
81 | # Visual C++ cache files
82 | ipch/
83 | *.aps
84 | *.ncb
85 | *.opensdf
86 | *.sdf
87 | *.cachefile
88 |
89 | # Visual Studio profiler
90 | *.psess
91 | *.vsp
92 | *.vspx
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 |
101 | # TeamCity is a build add-in
102 | _TeamCity*
103 |
104 | # DotCover is a Code Coverage Tool
105 | *.dotCover
106 |
107 | # NCrunch
108 | *.ncrunch*
109 | .*crunch*.local.xml
110 |
111 | # Installshield output folder
112 | [Ee]xpress/
113 |
114 | # DocProject is a documentation generator add-in
115 | DocProject/buildhelp/
116 | DocProject/Help/*.HxT
117 | DocProject/Help/*.HxC
118 | DocProject/Help/*.hhc
119 | DocProject/Help/*.hhk
120 | DocProject/Help/*.hhp
121 | DocProject/Help/Html2
122 | DocProject/Help/html
123 |
124 | # Click-Once directory
125 | publish/
126 |
127 | # Publish Web Output
128 | *.Publish.xml
129 | *.pubxml
130 |
131 | # NuGet Packages Directory
132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
133 | #packages/
134 |
135 | # Windows Azure Build Output
136 | csx
137 | *.build.csdef
138 |
139 | # Windows Store app package directory
140 | AppPackages/
141 |
142 | # Others
143 | sql/
144 | *.Cache
145 | ClientBin/
146 | [Ss]tyle[Cc]op.*
147 | ~$*
148 | *~
149 | *.dbmdl
150 | *.[Pp]ublish.xml
151 | *.pfx
152 | *.publishsettings
153 |
154 | # RIA/Silverlight projects
155 | Generated_Code/
156 |
157 | # Backup & report files from converting an old project file to a newer
158 | # Visual Studio version. Backup files are not needed, because we have git ;-)
159 | _UpgradeReport_Files/
160 | Backup*/
161 | UpgradeLog*.XML
162 | UpgradeLog*.htm
163 |
164 | # SQL Server files
165 | App_Data/*.mdf
166 | App_Data/*.ldf
167 |
168 | #############
169 | ## Windows detritus
170 | #############
171 |
172 | # Windows image file caches
173 | Thumbs.db
174 | ehthumbs.db
175 |
176 | # Folder config file
177 | Desktop.ini
178 |
179 | # Recycle Bin used on file shares
180 | $RECYCLE.BIN/
181 |
182 | # Mac crap
183 | .DS_Store
184 |
185 |
186 | #############
187 | ## Python
188 | #############
189 |
190 | *.py[co]
191 |
192 | # Packages
193 | *.egg
194 | *.egg-info
195 | dist/
196 | build/
197 | eggs/
198 | parts/
199 | var/
200 | sdist/
201 | develop-eggs/
202 | .installed.cfg
203 |
204 | # Installer logs
205 | pip-log.txt
206 |
207 | # Unit test / coverage reports
208 | .coverage
209 | .tox
210 |
211 | #Translations
212 | *.mo
213 |
214 | #Mr Developer
215 | .mr.developer.cfg
216 |
217 | out/
218 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/communication/Communication.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.communication;
2 |
3 | import java.io.InputStream;
4 | import java.io.OutputStream;
5 |
6 | import android.content.Context;
7 | import android.os.Bundle;
8 | import android.os.Handler;
9 | import android.os.Message;
10 | import android.util.Log;
11 |
12 | public abstract class Communication {
13 | public Handler mHandler;
14 |
15 | public static final String TAG = "MULTIWII"; // debug
16 |
17 | public boolean Connected = false;
18 | public String address = "";
19 | public String state = "";
20 |
21 | Context context;
22 |
23 | protected int mState;
24 |
25 | public long BytesSent=0;
26 | public long BytesReceived=0;
27 |
28 | // Constants that indicate the current connection state
29 | public static final int STATE_NONE = 0; // we're doing nothing
30 | public static final int STATE_CONNECTING = 2; // now initiating an outgoing
31 | // connection
32 | public static final int STATE_CONNECTED = 3; // now connected to a remote
33 | // device
34 |
35 | // Message types sent from the BluetoothChatService Handler
36 | public static final int MESSAGE_STATE_CHANGE = 1;
37 | public static final int MESSAGE_READ = 2;
38 | public static final int MESSAGE_WRITE = 3;
39 | public static final int MESSAGE_DEVICE_NAME = 4;
40 | public static final int MESSAGE_TOAST = 5;
41 |
42 | protected OutputStream outStream = null;
43 | protected InputStream inStream = null;
44 | public byte[] dataBuffer = null;
45 |
46 | // Key names received from the BluetoothChatService Handler
47 | public static final String DEVICE_NAME = "device_name";
48 | public static final String TOAST = "toast";
49 | public Communication(Context context) {
50 | this.context = context;
51 | }
52 | public Communication(Context context, Handler mHandler) {
53 | SetHandler(mHandler);
54 | this.context = context;
55 | }
56 |
57 | public void SetHandler(Handler mHandler) {
58 | this.mHandler = mHandler;
59 | Log.d("ccc", "Communication Got Handler. SetHandler()");
60 | }
61 |
62 | /**
63 | * Set the current state of the chat connection
64 | *
65 | * @param state
66 | * An integer defining the current connection state
67 | */
68 | protected synchronized void setState(int state) {
69 | // if (D)
70 | Log.d(TAG, "setState() " + mState + " -> " + state);
71 | mState = state;
72 |
73 | // Give the new state to the Handler so the UI Activity can update
74 | if (mHandler != null)
75 | mHandler.obtainMessage(MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
76 | else
77 | Log.d("ccc", "setState() Handle=null error state" + " -> " + state);
78 |
79 | }
80 |
81 | /**
82 | * Return the current connection state.
83 | */
84 | public synchronized int getState() {
85 | return mState;
86 | }
87 |
88 | /**
89 | * Sends Message to UI via Handler
90 | *
91 | * @param message
92 | */
93 | protected void sendMessageToUI_Toast(String message) {
94 | // Send a failure message back to the Activity
95 | if (mHandler != null) {
96 | Message msg = mHandler.obtainMessage(MESSAGE_TOAST);
97 | Bundle bundle = new Bundle();
98 | bundle.putString(TOAST, message);
99 | msg.setData(bundle);
100 | mHandler.sendMessage(msg);
101 | }
102 | }
103 |
104 | public void sendDeviceName(String deviceName) {
105 | // Send the name of the connected device back to the UI Activity
106 | if (mHandler != null) {
107 | Message msg = mHandler.obtainMessage(MESSAGE_DEVICE_NAME);
108 | Bundle bundle = new Bundle();
109 | bundle.putString(DEVICE_NAME, deviceName);
110 | msg.setData(bundle);
111 | mHandler.sendMessage(msg);
112 | }
113 | }
114 |
115 | public abstract void Enable();
116 |
117 | /**
118 | * After connection is made set Connected=true
119 | *
120 | * @param address
121 | * -address of device
122 | */
123 | public abstract boolean Connect(String address, int speed);
124 |
125 | public abstract boolean dataAvailable();
126 |
127 | public abstract byte Read();
128 |
129 | public boolean Write(byte[] arr){
130 | BytesSent+=arr.length;
131 | return true;
132 | }
133 |
134 | public abstract void Close();
135 |
136 | public abstract void Disable();
137 |
138 | protected abstract void connectionLost();
139 |
140 | public abstract String getConnectionState();
141 |
142 | public abstract CommunicationMode getMode();
143 |
144 | public abstract int getStrength();
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/MultiwiiRemote/gen/com/multiwii/multiwiiremote/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.multiwii.multiwiiremote;
9 |
10 | public final class R {
11 | public static final class array {
12 | public static final int comMode=0x7f050001;
13 | public static final int menuString=0x7f050002;
14 | public static final int rollPitchLimit=0x7f050000;
15 | }
16 | public static final class attr {
17 | }
18 | public static final class dimen {
19 | /** Default screen margins, per the Android Design guidelines.
20 |
21 | Customize dimensions originally defined in res/values/dimens.xml (such as
22 | screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
23 |
24 | */
25 | public static final int activity_horizontal_margin=0x7f060000;
26 | public static final int activity_vertical_margin=0x7f060001;
27 | }
28 | public static final class drawable {
29 | public static final int ic_launcher=0x7f020000;
30 | public static final int mwdragon_background=0x7f020001;
31 | public static final int progressbar_color=0x7f020002;
32 | }
33 | public static final class id {
34 | public static final int DualJoystickView=0x7f0a000b;
35 | public static final int accelOn=0x7f0a0012;
36 | public static final int aux1Btn=0x7f0a0001;
37 | public static final int aux2Btn=0x7f0a0002;
38 | public static final int aux3Btn=0x7f0a0003;
39 | public static final int aux4Btn=0x7f0a0006;
40 | public static final int button_scan=0x7f0a0010;
41 | public static final int chkUsePhoneHeading=0x7f0a000a;
42 | public static final int connect=0x7f0a0011;
43 | public static final int debugTxt=0x7f0a0009;
44 | public static final int joystickView=0x7f0a0005;
45 | public static final int menu_settings=0x7f0a0013;
46 | public static final int new_devices=0x7f0a000f;
47 | public static final int paired_devices=0x7f0a000d;
48 | public static final int status=0x7f0a0004;
49 | public static final int switchModes=0x7f0a0008;
50 | public static final int throttleView=0x7f0a0007;
51 | public static final int title_new_devices=0x7f0a000e;
52 | public static final int title_paired_devices=0x7f0a000c;
53 | public static final int webcamView=0x7f0a0000;
54 | }
55 | public static final class layout {
56 | public static final int activity_main=0x7f030000;
57 | public static final int device_list=0x7f030001;
58 | public static final int device_name=0x7f030002;
59 | }
60 | public static final class menu {
61 | public static final int main=0x7f090000;
62 | }
63 | public static final class string {
64 | public static final int action_settings=0x7f070001;
65 | public static final int app_name=0x7f070000;
66 | public static final int aux1=0x7f070002;
67 | public static final int aux2=0x7f070003;
68 | public static final int aux3=0x7f070004;
69 | public static final int aux4=0x7f070005;
70 | public static final int button_scan=0x7f07000d;
71 | public static final int connectionStatus=0x7f070006;
72 | public static final int menu=0x7f07000f;
73 | public static final int none_found=0x7f07000a;
74 | public static final int none_paired=0x7f070009;
75 | public static final int phone_heading=0x7f070011;
76 | /** DeviceListActivity
77 | */
78 | public static final int scanning=0x7f070007;
79 | public static final int select_device=0x7f070008;
80 | public static final int signal_strength=0x7f070010;
81 | public static final int switchModeBtn=0x7f07000e;
82 | public static final int title_other_devices=0x7f07000c;
83 | public static final int title_paired_devices=0x7f07000b;
84 | }
85 | public static final class style {
86 | /**
87 | Base application theme, dependent on API level. This theme is replaced
88 | by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
89 |
90 |
91 | Theme customizations available in newer API levels can go in
92 | res/values-vXX/styles.xml, while customizations related to
93 | backward-compatibility can go here.
94 |
95 | */
96 | public static final int AppBaseTheme=0x7f080001;
97 | /** Application theme.
98 | All customizations that are NOT specific to a particular API-level can go here.
99 | */
100 | public static final int AppTheme=0x7f080002;
101 | public static final int SpinnerStyle=0x7f080000;
102 | }
103 | public static final class xml {
104 | public static final int preferences=0x7f040000;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/communication/Wifi.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.communication;
2 |
3 | import java.io.IOException;
4 | import java.net.Socket;
5 | import java.util.List;
6 |
7 | import android.content.Context;
8 | import android.net.ConnectivityManager;
9 | import android.net.NetworkInfo;
10 | import android.net.wifi.WifiConfiguration;
11 | import android.net.wifi.WifiInfo;
12 | import android.net.wifi.WifiManager;
13 | import android.text.TextUtils;
14 | import android.util.Log;
15 |
16 | public class Wifi extends Communication {
17 | private Socket mySocket;
18 | private WifiManager wifiManager;
19 |
20 | public Wifi(Context context) {
21 | super(context);
22 | wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
23 |
24 | }
25 |
26 | private boolean isAlreadyConnectedToSSID(String ssid) {
27 | String mSSID = getCurrentSSID();
28 | if(mSSID == null) return false;
29 | return mSSID.equalsIgnoreCase(ssid);
30 | }
31 | public String getCurrentSSID() {
32 | String ssid = null;
33 | ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
34 | NetworkInfo networkInfo = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
35 | if (networkInfo.isConnected()) {
36 | final WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
37 | final WifiInfo connectionInfo = wifiManager.getConnectionInfo();
38 | if (connectionInfo != null && !TextUtils.isEmpty(connectionInfo.getSSID())) {
39 | ssid = connectionInfo.getSSID();
40 | }
41 | }
42 | return ssid;
43 | }
44 | private WifiConfiguration getConfiguredNetwork(WifiManager wifiManager, String ssid) {
45 | List myList = wifiManager.getConfiguredNetworks();
46 | for (WifiConfiguration current : myList) {
47 | String wifiConfigSSID = current.SSID.replace("\"", "");
48 | if (wifiConfigSSID.equalsIgnoreCase(ssid))
49 | return current;
50 | }
51 | return null;
52 | }
53 |
54 | public void setState(String state) {
55 | this.state = state;
56 | }
57 |
58 | public String getConnectionState() {
59 | return state;
60 | }
61 |
62 | public boolean Write(byte[] data) {
63 | super.Write(data);
64 | try {
65 | outStream.write(data);
66 | Connected = true;
67 | } catch (IOException e) {
68 | e.printStackTrace();
69 | Connected = false;
70 | }
71 | return Connected;
72 | }
73 |
74 | public boolean flush() {
75 | try {
76 | outStream.flush();
77 | return true;
78 | } catch (IOException e) {
79 | e.printStackTrace();
80 | return false;
81 | }
82 | }
83 |
84 | @Override
85 | public void Enable() {
86 | if (!wifiManager.isWifiEnabled())
87 | wifiManager.setWifiEnabled(true);
88 | }
89 |
90 | @Override
91 | public boolean Connect(String ip, int port) {
92 | Enable();
93 | address = ip + ":" + port;
94 | setState(STATE_CONNECTING);
95 | try {
96 | mySocket = new Socket(ip, port);
97 | mySocket.setKeepAlive(true);
98 | inStream = mySocket.getInputStream();
99 | outStream = mySocket.getOutputStream();
100 | setState(STATE_CONNECTED);
101 | //Connected = true;
102 | } catch (Exception e) {
103 | e.printStackTrace();
104 | connectionLost();
105 | return false;
106 | }
107 | //Log.d("connect", "connected!!!!!");
108 | return true;
109 | }
110 |
111 | @Override
112 | protected void connectionLost() {
113 | setState(STATE_NONE);
114 | //setState(e.getMessage());
115 | Connected = false;
116 | }
117 |
118 | @Override
119 | public boolean dataAvailable() {
120 | try {
121 | if (inStream == null)
122 | return false;
123 | return inStream.available() != 0;
124 | } catch (IOException e) {
125 | e.printStackTrace();
126 | return false;
127 | }
128 | }
129 |
130 | @Override
131 | public byte Read() {
132 | BytesReceived += 1;
133 | byte a = 0;
134 | try {
135 | a = (byte) inStream.read();
136 | } catch (IOException e) {
137 | e.printStackTrace();
138 | }
139 | return (byte) (a);
140 | }
141 |
142 | @Override
143 | public void Close() {
144 | Connected = false;
145 | if (mySocket != null && mySocket.isConnected())
146 | try {
147 | mySocket.close();
148 | } catch (IOException e) {
149 | e.printStackTrace();
150 | }
151 | }
152 |
153 | @Override
154 | public void Disable() {
155 | if (wifiManager.isWifiEnabled())
156 | wifiManager.setWifiEnabled(false);
157 | }
158 |
159 | @Override
160 | public int getStrength() {
161 | try {
162 | int rssi = wifiManager.getConnectionInfo().getRssi();
163 | int level = WifiManager.calculateSignalLevel(rssi, 10);
164 | int percentage = (int) ((level / 10.0) * 100);
165 | Log.d("aaa", "WiFI RSSI=" + String.valueOf(percentage));
166 | return percentage;
167 |
168 | } catch (Exception e) {
169 | return 0;
170 | }
171 | }
172 | @Override
173 | public CommunicationMode getMode()
174 | {
175 | return CommunicationMode.WIFI;
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | localhost
107 | 5050
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/communication/Bluetooth.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.communication;
2 |
3 | import java.io.IOException;
4 | import java.util.UUID;
5 |
6 | import android.annotation.SuppressLint;
7 | import android.bluetooth.BluetoothAdapter;
8 | import android.bluetooth.BluetoothDevice;
9 | import android.bluetooth.BluetoothSocket;
10 | import android.content.Context;
11 | import android.util.Log;
12 | import android.widget.Toast;
13 |
14 | public class Bluetooth extends Communication {
15 |
16 | private static final boolean D = true;
17 | private BluetoothAdapter mBluetoothAdapter = null;
18 | private BluetoothSocket btSocket = null;
19 | private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
20 |
21 | public Bluetooth(Context context) {
22 | super(context);
23 | }
24 |
25 | @Override
26 | public void Enable() {
27 | mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
28 | if (mBluetoothAdapter == null) {
29 | sendMessageToUI_Toast("Bluetooth is not available on your device");
30 | // finish();
31 | return;
32 | }
33 |
34 | if (!mBluetoothAdapter.isEnabled()) {
35 | mBluetoothAdapter.enable();
36 | return;
37 | }
38 |
39 | if (D)
40 | Log.d(TAG, "+++ DONE IN ON CREATE, GOT LOCAL BT ADAPTER +++");
41 |
42 | }
43 |
44 | @Override
45 | public boolean Connect(String address, int speed) {
46 | Enable();
47 | setState(STATE_CONNECTING);
48 | if (mBluetoothAdapter.isEnabled()) {
49 | try {
50 | GetRemoteDevice(address);
51 | btSocket.connect();
52 | Connected = true;
53 |
54 | Log.d(TAG, "BT connection established, data transfer link open.");
55 | setState(STATE_CONNECTED);
56 | } catch (IOException e) {
57 | try {
58 | btSocket.close();
59 | Connected = false;
60 |
61 | //Toast.makeText(context, context.getString(R.string.Unabletoconnect), Toast.LENGTH_LONG).show();
62 | } catch (IOException e2) {
63 | Log.e(TAG, "ON RESUME: Unable to close socket during connection failure", e2);
64 | setState(STATE_NONE);
65 | }
66 | }
67 |
68 | // Create a data stream so we can talk to server.
69 | if (D)
70 | Log.d(TAG, "+ getOutputStream getInputStream +");
71 |
72 | try {
73 | outStream = btSocket.getOutputStream();
74 | inStream = btSocket.getInputStream();
75 |
76 | } catch (IOException e) {
77 | Log.e(TAG, "ON RESUME: Output stream creation failed.", e);
78 | setState(STATE_NONE);
79 | }
80 | }
81 | return Connected;
82 | }
83 |
84 | @Override
85 | public boolean dataAvailable() {
86 | boolean a = false;
87 |
88 | try {
89 | if (Connected)
90 | a = inStream.available() > 0;
91 |
92 | } catch (IOException e) {
93 | e.printStackTrace();
94 | }
95 |
96 | return a;
97 | }
98 |
99 | @Override
100 | public byte Read() {
101 | BytesReceived += 1;
102 | byte a = 0;
103 | try {
104 | a = (byte) inStream.read();
105 | } catch (IOException e) {
106 | e.printStackTrace();
107 | }
108 | return (byte) (a);
109 | }
110 |
111 | @Override
112 | public boolean Write(byte[] arr) {
113 | super.Write(arr);
114 | try {
115 | if (Connected)
116 | outStream.write(arr);
117 | return true;
118 | } catch (IOException e) {
119 | Log.e(TAG, "SEND : Exception during write.", e);
120 | CloseSocket();
121 |
122 | Toast.makeText(context, "Write error", Toast.LENGTH_LONG).show();
123 | return false;
124 | }
125 |
126 | }
127 |
128 | @Override
129 | public void Close() {
130 | CloseSocket();
131 | }
132 |
133 | @Override
134 | public void Disable() {
135 | try {
136 | mBluetoothAdapter.disable();
137 | } catch (Exception e) {
138 | sendMessageToUI_Toast("Can't disable BT");
139 | }
140 | }
141 |
142 | @SuppressLint("NewApi")
143 | private void GetRemoteDevice(String address) {
144 | if (D) {
145 | Log.d(TAG, "+ ON RESUME +");
146 | Log.d(TAG, "+ ABOUT TO ATTEMPT CLIENT CONNECT +");
147 | }
148 |
149 | BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
150 | try {
151 |
152 | btSocket = device.createRfcommSocketToServiceRecord(MY_UUID);
153 |
154 | } catch (IOException e) {
155 | Log.e(TAG, "ON RESUME: Socket creation failed.", e);
156 | sendMessageToUI_Toast("Unable to connect");
157 | }
158 |
159 | if (mBluetoothAdapter.isDiscovering())
160 | mBluetoothAdapter.cancelDiscovery();
161 | }
162 |
163 | public void CloseSocket() {
164 | if (outStream != null) {
165 | try {
166 | outStream.flush();
167 | } catch (IOException e) {
168 | Log.e(TAG, "ON PAUSE: Couldn't flush output stream.", e);
169 | sendMessageToUI_Toast("Unable to close socket");
170 | }
171 | }
172 |
173 | try {
174 | if (btSocket != null)
175 | btSocket.close();
176 | Connected = false;
177 | } catch (Exception e2) {
178 | Log.e(TAG, "ON PAUSE: Unable to close socket.", e2);
179 | Toast.makeText(context, "Unable to close socket", Toast.LENGTH_LONG).show();
180 | }
181 |
182 | }
183 |
184 | @Override
185 | public String getConnectionState() {
186 | // TODO Auto-generated method stub
187 | return null;
188 | }
189 |
190 | @Override
191 | public int getStrength() {
192 | // TODO Auto-generated method stub
193 | return 0;
194 | }
195 | @Override
196 | public CommunicationMode getMode()
197 | {
198 | return CommunicationMode.BLUETOOTH;
199 | }
200 |
201 | @Override
202 | protected void connectionLost() {
203 | // TODO Auto-generated method stub
204 |
205 | }
206 |
207 | }
208 |
--------------------------------------------------------------------------------
/MultiwiiRemote/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
19 |
20 |
24 |
25 |
33 |
34 |
43 |
44 |
52 |
53 |
61 |
62 |
71 |
72 |
79 |
80 |
88 |
89 |
96 |
97 |
112 |
113 |
121 |
122 |
134 |
135 |
136 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/joystick/DualJoystickView.java:
--------------------------------------------------------------------------------
1 | package view.joystick;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.MotionEvent;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.LinearLayout;
13 |
14 | public class DualJoystickView extends LinearLayout {
15 | @SuppressWarnings("unused")
16 | private static final String TAG = DualJoystickView.class.getSimpleName();
17 |
18 | private final boolean D = false;
19 | private Paint dbgPaint1;
20 |
21 | public JoystickView stickL;
22 | public JoystickView stickR;
23 |
24 | private View pad;
25 |
26 | public DualJoystickView(Context context) {
27 | super(context);
28 | stickL = new JoystickView(context);
29 | stickR = new JoystickView(context);
30 | initDualJoystickView();
31 | }
32 |
33 | public DualJoystickView(Context context, AttributeSet attrs) {
34 | super(context, attrs);
35 | stickL = new JoystickView(context, attrs);
36 | stickR = new JoystickView(context, attrs);
37 | initDualJoystickView();
38 | }
39 |
40 | private void initDualJoystickView() {
41 | setOrientation(LinearLayout.HORIZONTAL);
42 |
43 | if ( D ) {
44 | dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
45 | dbgPaint1.setColor(Color.CYAN);
46 | dbgPaint1.setStrokeWidth(1);
47 | dbgPaint1.setStyle(Paint.Style.STROKE);
48 | }
49 |
50 | pad = new View(getContext());
51 | }
52 |
53 | @Override
54 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
55 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
56 | removeView(stickL);
57 | removeView(stickR);
58 |
59 | float padW = getMeasuredWidth()-(getMeasuredHeight()*2);
60 | int joyWidth = (int) ((getMeasuredWidth()-padW)/2);
61 | LayoutParams joyLParams = new LayoutParams(joyWidth,getMeasuredHeight());
62 |
63 | stickL.setLayoutParams(joyLParams);
64 | stickR.setLayoutParams(joyLParams);
65 |
66 | stickL.TAG = "L";
67 | stickR.TAG = "R";
68 | //stickL.setPointerId(JoystickView.INVALID_POINTER_ID);
69 | //stickR.setPointerId(JoystickView.INVALID_POINTER_ID);
70 |
71 | addView(stickL);
72 |
73 | ViewGroup.LayoutParams padLParams = new ViewGroup.LayoutParams((int) padW,getMeasuredHeight());
74 | removeView(pad);
75 | pad.setLayoutParams(padLParams);
76 | addView(pad);
77 |
78 | addView(stickR);
79 | }
80 |
81 | @Override
82 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
83 | super.onLayout(changed, l, t, r, b);
84 | stickR.setTouchOffset(stickR.getLeft(), stickR.getTop());
85 | }
86 |
87 | public void setAutoReturnToCenter(boolean left, boolean right) {
88 | stickL.setAutoReturnToCenter(left);
89 | stickR.setAutoReturnToCenter(right);
90 | }
91 |
92 | public void setOnJostickMovedListener(JoystickMovedListener left, JoystickMovedListener right) {
93 | stickL.setOnJostickMovedListener(left);
94 | stickR.setOnJostickMovedListener(right);
95 | }
96 |
97 | public void setOnJostickClickedListener(JoystickClickedListener left, JoystickClickedListener right) {
98 | stickL.setOnJostickClickedListener(left);
99 | stickR.setOnJostickClickedListener(right);
100 | }
101 |
102 | public void setYAxisInverted(boolean leftYAxisInverted, boolean rightYAxisInverted) {
103 | stickL.setYAxisInverted(leftYAxisInverted);
104 | stickL.setYAxisInverted(rightYAxisInverted);
105 | }
106 |
107 | public void setMovementConstraint(int movementConstraint) {
108 | stickL.setMovementConstraint(movementConstraint);
109 | stickR.setMovementConstraint(movementConstraint);
110 | }
111 |
112 | public void setMovementRange(float movementRangeLeft, float movementRangeRight) {
113 | stickL.setMovementRange(movementRangeLeft);
114 | stickR.setMovementRange(movementRangeRight);
115 | }
116 |
117 | public void setMoveResolution(float leftMoveResolution, float rightMoveResolution) {
118 | stickL.setMoveResolution(leftMoveResolution);
119 | stickR.setMoveResolution(rightMoveResolution);
120 | }
121 |
122 | public void setUserCoordinateSystem(int leftCoordinateSystem, int rightCoordinateSystem) {
123 | stickL.setUserCoordinateSystem(leftCoordinateSystem);
124 | stickR.setUserCoordinateSystem(rightCoordinateSystem);
125 | }
126 |
127 | @Override
128 | protected void dispatchDraw(Canvas canvas) {
129 | super.dispatchDraw(canvas);
130 | if (D) {
131 | canvas.drawRect(1, 1, getMeasuredWidth()-1, getMeasuredHeight()-1, dbgPaint1);
132 | }
133 | }
134 |
135 | @Override
136 | public boolean dispatchTouchEvent(MotionEvent ev){
137 | Log.d("DualJoystickView", "dispatch touch event");
138 | boolean l = stickL.dispatchTouchEvent(ev);
139 | boolean r = stickR.dispatchTouchEvent(ev);
140 | return true;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/RCSignals.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 | import com.multiwii.Utilities.Utilities;
4 |
5 | public class RCSignals {
6 |
7 | public enum AdjustMode {
8 | THROTTLE("T: ", (byte) 3), ROLL("R: ", (byte) 0), PITCH("P: ", (byte) 1), YAW("Y: ", (byte) 2);
9 | String value;
10 | byte id;
11 |
12 | private AdjustMode(String value, byte id) {
13 | this.value = value;
14 | this.id = id;
15 | }
16 | public AdjustMode next(AdjustMode t) {
17 | if (t.ordinal() == AdjustMode.values().length - 1)
18 | return AdjustMode.values()[0];
19 | else
20 | return AdjustMode.values()[t.ordinal() + 1];
21 | }
22 | public String getValue() {
23 | return value;
24 | }
25 | public byte getId() {
26 | return id;
27 | }
28 | }
29 | public static byte ROLL = 0;
30 | public static byte PITCH = 1;
31 | public static byte YAW = 2;
32 | public static byte THROTTLE = 3;
33 | public static byte AUX1 = 4;
34 | public static byte AUX2 = 5;
35 | public static byte AUX3 = 6;
36 | public static byte AUX4 = 7;
37 | public AdjustMode adjustMode = AdjustMode.THROTTLE;
38 |
39 | private int[] rc_signals_raw = new int[8];
40 | private int[] rc_signals_trim = new int[8];
41 | private int[] rc_signals = new int[8];
42 | private int RC_MIN = 1000;
43 | private int RC_MAX = 2000;
44 | private int RC_MID = (RC_MAX - RC_MIN) / 2 + RC_MIN;
45 |
46 | public int ThrottleResolution = 10;
47 | public int TrimRoll = 0;
48 | public int TrimPitch = 0;
49 | public int RollPitchLimit = 500;
50 | public int ThrottleLimit = 500;
51 | public int YAW_RESOLUTION = 5;
52 |
53 | public RCSignals() {
54 | resetRcSignals();
55 | }
56 | public void switchMode() {
57 | adjustMode = AdjustMode.THROTTLE.next(adjustMode);
58 | if(isFlying() && (adjustMode == AdjustMode.ROLL || adjustMode == AdjustMode.PITCH))
59 | adjustMode = AdjustMode.YAW;
60 | }
61 | public void adjustRcValue(int sign) {
62 | switch (adjustMode) {
63 | case THROTTLE:
64 | set(THROTTLE, get(THROTTLE) + ThrottleResolution * sign);
65 | break;
66 | case ROLL:
67 | trim(ROLL, trim(ROLL) + sign);
68 | break;
69 | case PITCH:
70 | trim(PITCH, trim(PITCH) + sign);
71 | break;
72 | case YAW:
73 | set(YAW, get(YAW) + YAW_RESOLUTION * sign);
74 | break;
75 | }
76 | }
77 | private void resetRcSignals() {
78 | rc_signals_raw[ROLL] = RC_MID;
79 | rc_signals_raw[PITCH] = RC_MID;
80 | rc_signals_raw[YAW] = RC_MID;
81 | rc_signals_raw[THROTTLE] = RC_MIN;
82 | rc_signals_raw[AUX1] = RC_MIN;
83 | rc_signals_raw[AUX2] = RC_MIN;
84 | rc_signals_raw[AUX3] = RC_MIN;
85 | rc_signals_raw[AUX4] = RC_MIN;
86 | }
87 |
88 | private void updateTrimedValues() {
89 | for(int x = 0; x < rc_signals.length; x++)
90 | rc_signals[x] = rc_signals_raw[x];
91 | rc_signals[ROLL] = rc_signals_raw[ROLL] + TrimRoll;
92 | rc_signals[PITCH] = rc_signals_raw[PITCH] + TrimPitch;
93 |
94 | for(int x = 0; x < rc_signals.length; x++) { //Verify bounds
95 | if(rc_signals[x] < RC_MIN) rc_signals[x] = RC_MIN;
96 | if(rc_signals[x] > RC_MAX) rc_signals[x] = RC_MAX;
97 | }
98 | }
99 |
100 | public boolean isFlying() {
101 | return rc_signals_raw[THROTTLE] > 1100;
102 | }
103 |
104 | public void setRoll(int roll) {
105 | rc_signals_raw[ROLL] = roll;
106 | }
107 |
108 | public void setPitch(int pitch) {
109 | rc_signals_raw[PITCH] = pitch;
110 | }
111 |
112 | public void setThrottle(int throttle){ rc_signals_raw[THROTTLE] = throttle; }
113 |
114 | public void setYaw(int yaw) { rc_signals_raw[YAW] = yaw; }
115 |
116 | public void setAdjustedRoll(int roll) {
117 | setRoll((int) (Utilities.map(roll, -500, 500, -RollPitchLimit, RollPitchLimit) + 1500));
118 | }
119 | public void setAdjustedPitch(int pitch) {
120 | setPitch((int) (Utilities.map(pitch, -500, 500, -RollPitchLimit, RollPitchLimit) + 1500));
121 | }
122 | public void setAdjustedThrottle(int throttle) {
123 | setThrottle((int) (Utilities.map(throttle, -500, 500, 0, ThrottleLimit) + 1000));//adjust throttle range....
124 | }
125 |
126 | public void setAdjustedYaw(int yaw) {
127 | setYaw((int) (Utilities.map(yaw, -500, 500, -ThrottleLimit, ThrottleLimit) + 1500));
128 | }
129 |
130 | public void setMin(byte id) {
131 | rc_signals_raw[id] = RC_MIN;
132 | }
133 |
134 | public void setMid(byte id) {
135 | rc_signals_raw[id] = RC_MID;
136 | }
137 |
138 | public void setMax(byte id) {
139 | rc_signals_raw[id] = RC_MAX;
140 | }
141 |
142 | public void setMin(byte[] idArray) {
143 | for(byte id : idArray)
144 | rc_signals_raw[id] = RC_MIN;
145 | }
146 |
147 | public void setMid(byte[] idArray) {
148 | for(byte id : idArray)
149 | rc_signals_raw[id] = RC_MID;
150 | }
151 |
152 | public void setMax(byte[] idArray) {
153 | for(byte id : idArray)
154 | rc_signals_raw[id] = RC_MAX;
155 | }
156 |
157 | public void set(byte id, boolean isMax) {
158 | if(isMax)
159 | setMax(id);
160 | else
161 | setMin(id);
162 | }
163 |
164 | public int get(byte id) {
165 | updateTrimedValues();
166 | return rc_signals[id];
167 | }
168 | public void set(byte id, int value) {
169 | if(value >= RC_MIN && value <= RC_MAX)
170 | rc_signals_raw[id] = value;
171 | if(rc_signals_raw[THROTTLE] >= 1030)
172 | setMax(AUX1);
173 | else
174 | setMin(AUX1);
175 | }
176 |
177 | public void trim(byte id, int newValue) {
178 | rc_signals_trim[id] = newValue;
179 | }
180 |
181 | public int trim(byte id) {
182 | return rc_signals_trim[id];
183 | }
184 | //TODO
185 | public int raw_values(byte id) {
186 | return raw_values()[id];
187 | }
188 | //TODO
189 | public int[] raw_values() {
190 | return rc_signals_raw;
191 | }
192 |
193 | public int[] get() {
194 | updateTrimedValues();
195 | return rc_signals;
196 | }
197 |
198 | @Override
199 | public String toString() {
200 | return "Throttle: " + get(THROTTLE) + "\n" + toStringNoThrottle();
201 | }
202 |
203 | public String toStringNoThrottle() {
204 | return "Roll: " + get(ROLL) + "\n"
205 | + "Pitch: " + get(PITCH) + "\n"
206 | + "Yaw: " + get(YAW) + "\n";
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/mjpeg/MjpegView.java:
--------------------------------------------------------------------------------
1 | package view.mjpeg;
2 |
3 | import java.io.IOException;
4 |
5 | import android.content.Context;
6 | import android.graphics.Bitmap;
7 | import android.graphics.Canvas;
8 | import android.graphics.Color;
9 | import android.graphics.Paint;
10 | import android.graphics.PorterDuff;
11 | import android.graphics.PorterDuffXfermode;
12 | import android.graphics.Rect;
13 | import android.graphics.Typeface;
14 | import android.util.AttributeSet;
15 | import android.view.SurfaceHolder;
16 | import android.view.SurfaceView;
17 |
18 | public class MjpegView extends SurfaceView implements SurfaceHolder.Callback {
19 | public final static int POSITION_UPPER_LEFT = 9;
20 | public final static int POSITION_UPPER_RIGHT = 3;
21 | public final static int POSITION_LOWER_LEFT = 12;
22 | public final static int POSITION_LOWER_RIGHT = 6;
23 |
24 | public final static int SIZE_STANDARD = 1;
25 | public final static int SIZE_BEST_FIT = 4;
26 | public final static int SIZE_FULLSCREEN = 8;
27 |
28 | private MjpegViewThread thread;
29 | private MjpegInputStream mIn = null;
30 | private boolean showFps = false;
31 | private boolean mRun = false;
32 | private boolean surfaceDone = false;
33 | private Paint overlayPaint;
34 | private int overlayTextColor;
35 | private int overlayBackgroundColor;
36 | private int ovlPos;
37 | private int dispWidth;
38 | private int dispHeight;
39 | private int displayMode;
40 |
41 | public class MjpegViewThread extends Thread {
42 | private SurfaceHolder mSurfaceHolder;
43 | private int frameCounter = 0;
44 | private long start;
45 | private Bitmap ovl;
46 |
47 | public MjpegViewThread(SurfaceHolder surfaceHolder, Context context) { mSurfaceHolder = surfaceHolder; }
48 |
49 | private Rect destRect(int bmw, int bmh) {
50 | int tempx;
51 | int tempy;
52 | if (displayMode == MjpegView.SIZE_STANDARD) {
53 | tempx = (dispWidth / 2) - (bmw / 2);
54 | tempy = (dispHeight / 2) - (bmh / 2);
55 | return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
56 | }
57 | if (displayMode == MjpegView.SIZE_BEST_FIT) {
58 | float bmasp = (float) bmw / (float) bmh;
59 | bmw = dispWidth;
60 | bmh = (int) (dispWidth / bmasp);
61 | if (bmh > dispHeight) {
62 | bmh = dispHeight;
63 | bmw = (int) (dispHeight * bmasp);
64 | }
65 | tempx = (dispWidth / 2) - (bmw / 2);
66 | tempy = (dispHeight / 2) - (bmh / 2);
67 | return new Rect(tempx, tempy, bmw + tempx, bmh + tempy);
68 | }
69 | if (displayMode == MjpegView.SIZE_FULLSCREEN) return new Rect(0, 0, dispWidth, dispHeight);
70 | return null;
71 | }
72 |
73 | public void setSurfaceSize(int width, int height) {
74 | synchronized(mSurfaceHolder) {
75 | dispWidth = width;
76 | dispHeight = height;
77 | }
78 | }
79 |
80 | private Bitmap makeFpsOverlay(Paint p, String text) {
81 | Rect b = new Rect();
82 | p.getTextBounds(text, 0, text.length(), b);
83 | int bwidth = b.width()+2;
84 | int bheight = b.height()+2;
85 | Bitmap bm = Bitmap.createBitmap(bwidth, bheight, Bitmap.Config.ARGB_8888);
86 | Canvas c = new Canvas(bm);
87 | p.setColor(overlayBackgroundColor);
88 | c.drawRect(0, 0, bwidth, bheight, p);
89 | p.setColor(overlayTextColor);
90 | c.drawText(text, -b.left+1, (bheight/2)-((p.ascent()+p.descent())/2)+1, p);
91 | return bm;
92 | }
93 |
94 | public void run() {
95 | start = System.currentTimeMillis();
96 | PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.DST_OVER);
97 | Bitmap bm;
98 | int width;
99 | int height;
100 | Rect destRect;
101 | Canvas c = null;
102 | Paint p = new Paint();
103 | String fps = "";
104 | while (mRun) {
105 | if(surfaceDone) {
106 | try {
107 | c = mSurfaceHolder.lockCanvas();
108 | synchronized (mSurfaceHolder) {
109 | try {
110 | bm = mIn.readMjpegFrame();
111 | destRect = destRect(bm.getWidth(),bm.getHeight());
112 | c.drawColor(Color.BLACK);
113 | c.drawBitmap(bm, null, destRect, p);
114 | if(showFps) {
115 | p.setXfermode(mode);
116 | if(ovl != null) {
117 | height = ((ovlPos & 1) == 1) ? destRect.top : destRect.bottom-ovl.getHeight();
118 | width = ((ovlPos & 8) == 8) ? destRect.left : destRect.right -ovl.getWidth();
119 | c.drawBitmap(ovl, width, height, null);
120 | }
121 | p.setXfermode(null);
122 | frameCounter++;
123 | if((System.currentTimeMillis() - start) >= 1000) {
124 | fps = String.valueOf(frameCounter)+"fps";
125 | frameCounter = 0;
126 | start = System.currentTimeMillis();
127 | ovl = makeFpsOverlay(overlayPaint, fps);
128 | }
129 | }
130 | } catch (IOException e) {}
131 | }
132 | } finally { if (c != null) mSurfaceHolder.unlockCanvasAndPost(c); }
133 | }
134 | }
135 | }
136 | }
137 |
138 | private void init(Context context) {
139 | SurfaceHolder holder = getHolder();
140 | holder.addCallback(this);
141 | thread = new MjpegViewThread(holder, context);
142 | setFocusable(true);
143 | overlayPaint = new Paint();
144 | overlayPaint.setTextAlign(Paint.Align.LEFT);
145 | overlayPaint.setTextSize(12);
146 | overlayPaint.setTypeface(Typeface.DEFAULT);
147 | overlayTextColor = Color.WHITE;
148 | overlayBackgroundColor = Color.BLACK;
149 | ovlPos = MjpegView.POSITION_LOWER_RIGHT;
150 | displayMode = MjpegView.SIZE_STANDARD;
151 | dispWidth = getWidth();
152 | dispHeight = getHeight();
153 | }
154 |
155 | public void startPlayback() {
156 | if(mIn != null) {
157 | mRun = true;
158 | thread.start();
159 | }
160 | }
161 |
162 | public void stopPlayback() {
163 | mRun = false;
164 | boolean retry = true;
165 | while(retry) {
166 | try {
167 | thread.join();
168 | retry = false;
169 | } catch (InterruptedException e) {}
170 | }
171 | }
172 |
173 | public MjpegView(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
174 | public void surfaceChanged(SurfaceHolder holder, int f, int w, int h) { thread.setSurfaceSize(w, h); }
175 |
176 | public void surfaceDestroyed(SurfaceHolder holder) {
177 | surfaceDone = false;
178 | stopPlayback();
179 | }
180 |
181 | public MjpegView(Context context) {
182 | super(context);
183 | init(context);
184 | }
185 | public void surfaceCreated(SurfaceHolder holder) {
186 | surfaceDone = true;
187 | }
188 | public void showFps(boolean b) {
189 | showFps = b;
190 | }
191 | public void setSource(MjpegInputStream source) {
192 | mIn = source;
193 | startPlayback();
194 | }
195 | public void setOverlayPaint(Paint p) {
196 | overlayPaint = p;
197 | }
198 | public void setOverlayTextColor(int c) {
199 | overlayTextColor = c;
200 | }
201 | public void setOverlayBackgroundColor(int c) {
202 | overlayBackgroundColor = c;
203 | }
204 | public void setOverlayPosition(int p) {
205 | ovlPos = p;
206 | }
207 | public void setDisplayMode(int s) {
208 | displayMode = s;
209 | }
210 | }
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/communication/DeviceListActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2009 The Android Open Source Project
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.multiwii.communication;
18 |
19 | import java.util.Set;
20 |
21 | import com.multiwii.multiwiiremote.R;
22 |
23 | import android.app.Activity;
24 | import android.bluetooth.BluetoothAdapter;
25 | import android.bluetooth.BluetoothDevice;
26 | import android.content.BroadcastReceiver;
27 | import android.content.Context;
28 | import android.content.Intent;
29 | import android.content.IntentFilter;
30 | import android.os.Bundle;
31 | import android.util.Log;
32 | import android.view.View;
33 | import android.view.Window;
34 | import android.view.View.OnClickListener;
35 | import android.widget.AdapterView;
36 | import android.widget.ArrayAdapter;
37 | import android.widget.Button;
38 | import android.widget.ListView;
39 | import android.widget.TextView;
40 | import android.widget.AdapterView.OnItemClickListener;
41 |
42 | /**
43 | * This Activity appears as a dialog. It lists any paired devices and
44 | * devices detected in the area after discovery. When a device is chosen
45 | * by the user, the MAC address of the device is sent back to the parent
46 | * Activity in the result Intent.
47 | */
48 | public class DeviceListActivity extends Activity {
49 | // Debugging
50 | private static final String TAG = "DeviceListActivity";
51 | private static final boolean D = true;
52 |
53 | // Return Intent extra
54 | public static String EXTRA_DEVICE_ADDRESS = "device_address";
55 |
56 | // Member fields
57 | private BluetoothAdapter mBtAdapter;
58 | private ArrayAdapter mPairedDevicesArrayAdapter;
59 | private ArrayAdapter mNewDevicesArrayAdapter;
60 |
61 | @Override
62 | protected void onCreate(Bundle savedInstanceState) {
63 | super.onCreate(savedInstanceState);
64 |
65 | // Setup the window
66 | requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
67 | setContentView(R.layout.device_list);
68 |
69 | // Set result CANCELED incase the user backs out
70 | setResult(Activity.RESULT_CANCELED);
71 |
72 | // Initialize the button to perform device discovery
73 | Button scanButton = (Button) findViewById(R.id.button_scan);
74 | scanButton.setOnClickListener(new OnClickListener() {
75 | public void onClick(View v) {
76 | doDiscovery();
77 | v.setVisibility(View.GONE);
78 | }
79 | });
80 |
81 | // Initialize array adapters. One for already paired devices and
82 | // one for newly discovered devices
83 | mPairedDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name);
84 | mNewDevicesArrayAdapter = new ArrayAdapter(this, R.layout.device_name);
85 |
86 | // Find and set up the ListView for paired devices
87 | ListView pairedListView = (ListView) findViewById(R.id.paired_devices);
88 | pairedListView.setAdapter(mPairedDevicesArrayAdapter);
89 | pairedListView.setOnItemClickListener(mDeviceClickListener);
90 |
91 | // Find and set up the ListView for newly discovered devices
92 | ListView newDevicesListView = (ListView) findViewById(R.id.new_devices);
93 | newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
94 | newDevicesListView.setOnItemClickListener(mDeviceClickListener);
95 |
96 | // Register for broadcasts when a device is discovered
97 | IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
98 | this.registerReceiver(mReceiver, filter);
99 |
100 | // Register for broadcasts when discovery has finished
101 | filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
102 | this.registerReceiver(mReceiver, filter);
103 |
104 | // Get the local Bluetooth adapter
105 | mBtAdapter = BluetoothAdapter.getDefaultAdapter();
106 |
107 | // Get a set of currently paired devices
108 | Set pairedDevices = mBtAdapter.getBondedDevices();
109 |
110 | // If there are paired devices, add each one to the ArrayAdapter
111 | if (pairedDevices.size() > 0) {
112 | findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
113 | for (BluetoothDevice device : pairedDevices) {
114 | mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
115 | }
116 | } else {
117 | String noDevices = getResources().getText(R.string.none_paired).toString();
118 | mPairedDevicesArrayAdapter.add(noDevices);
119 | }
120 | }
121 |
122 | @Override
123 | protected void onDestroy() {
124 | super.onDestroy();
125 |
126 | // Make sure we're not doing discovery anymore
127 | if (mBtAdapter != null) {
128 | mBtAdapter.cancelDiscovery();
129 | }
130 |
131 | // Unregister broadcast listeners
132 | this.unregisterReceiver(mReceiver);
133 | }
134 |
135 | /**
136 | * Start device discover with the BluetoothAdapter
137 | */
138 | private void doDiscovery() {
139 | if (D) Log.d(TAG, "doDiscovery()");
140 |
141 | // Indicate scanning in the title
142 | setProgressBarIndeterminateVisibility(true);
143 | setTitle(R.string.scanning);
144 |
145 | // Turn on sub-title for new devices
146 | findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE);
147 |
148 | // If we're already discovering, stop it
149 | if (mBtAdapter.isDiscovering()) {
150 | mBtAdapter.cancelDiscovery();
151 | }
152 |
153 | // Request discover from BluetoothAdapter
154 | mBtAdapter.startDiscovery();
155 | }
156 |
157 | // The on-click listener for all devices in the ListViews
158 | private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
159 | public void onItemClick(AdapterView> av, View v, int arg2, long arg3) {
160 | // Cancel discovery because it's costly and we're about to connect
161 | mBtAdapter.cancelDiscovery();
162 |
163 | // Get the device MAC address, which is the last 17 chars in the View
164 | String info = ((TextView) v).getText().toString();
165 | String address = info.substring(info.length() - 17);
166 |
167 | // Create the result Intent and include the MAC address
168 | Intent intent = new Intent();
169 | intent.putExtra(EXTRA_DEVICE_ADDRESS, address);
170 |
171 | // Set result and finish this Activity
172 | setResult(Activity.RESULT_OK, intent);
173 | finish();
174 | }
175 | };
176 |
177 | // The BroadcastReceiver that listens for discovered devices and
178 | // changes the title when discovery is finished
179 | private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
180 | @Override
181 | public void onReceive(Context context, Intent intent) {
182 | String action = intent.getAction();
183 |
184 | // When discovery finds a device
185 | if (BluetoothDevice.ACTION_FOUND.equals(action)) {
186 | // Get the BluetoothDevice object from the Intent
187 | BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
188 | // If it's already paired, skip it, because it's been listed already
189 | if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
190 | mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress());
191 | }
192 | // When discovery is finished, change the Activity title
193 | } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
194 | setProgressBarIndeterminateVisibility(false);
195 | setTitle(R.string.select_device);
196 | if (mNewDevicesArrayAdapter.getCount() == 0) {
197 | String noDevices = getResources().getText(R.string.none_found).toString();
198 | mNewDevicesArrayAdapter.add(noDevices);
199 | }
200 | }
201 | }
202 | };
203 |
204 | }
205 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/App.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 |
4 |
5 | import java.util.Locale;
6 |
7 | import com.multiwii.communication.Bluetooth;
8 | import com.multiwii.communication.Communication;
9 | import com.multiwii.communication.CommunicationMode;
10 | import com.multiwii.communication.Wifi;
11 | import com.multiwii.protocol.MultiWii230;
12 | import com.multiwii.protocol.MultirotorData;
13 | import com.multiwii.Utilities.Sensors;
14 | import com.multiwii.Utilities.SoundManager;
15 | import com.multiwii.Utilities.TTS;
16 | import com.multiwii.Utilities.Utilities;
17 | import com.multiwii.Utilities.VarioSoundClass;
18 |
19 | import android.annotation.SuppressLint;
20 | import android.app.Application;
21 | import android.content.SharedPreferences;
22 | import android.content.SharedPreferences.Editor;
23 | import android.os.Handler;
24 | import android.preference.PreferenceManager;
25 | import static com.multiwii.multiwiiremote.App.SettingsConstants.*;
26 |
27 | public class App extends Application implements Sensors.MagAccListener {
28 |
29 | /////Settings variables/////////
30 | public int LowSignalThreshold;
31 | public int RollPitchLimit;
32 | public boolean UIDebug;
33 | public int RefreshRate = 50; //TODO ADD TO XML
34 | public int TrimRoll;
35 | public int TrimPitch;
36 | public int ThrottleResolution;
37 | public int BaudRate;
38 | public String IpAddress;
39 | public int IpPort;
40 | public boolean UseCamera;
41 | public float SensorFilterAlpha;
42 | public boolean PreventExitWhenFlying;
43 | public boolean TextToSpeach;
44 | public CommunicationMode comMode;
45 | public String ssid;
46 |
47 |
48 |
49 | private MainActivity mainActivity;
50 | public String Aux1Txt;
51 | public String Aux2Txt;
52 | public String Aux3Txt;
53 | public String Aux4Txt;
54 |
55 | public void setMainActivity(MainActivity mainActivity) {
56 | this.mainActivity = mainActivity;
57 | }
58 |
59 | public MainActivity getMainActivity() {
60 | return mainActivity;
61 | }
62 |
63 | public enum SettingsConstants {
64 | LOWSIGNALTHRESHOLD(30),
65 | TEXTTOSPEACH(true),
66 | UIDEBUG(false),
67 | REFRESHRATE(40), //TODO add xml
68 | TRIMROLL(0),
69 | TRIMPITCH(0),
70 | THROTTLERESOLUTION(10),
71 | BAUDRATE("115200"),
72 | IPADDRESS("192.168.1.1"),
73 | IPPORT(8082),
74 | AUX1TXT("AUX 1"),
75 | AUX2TXT("AUX 2"),
76 | AUX3TXT("AUX 3"),
77 | AUX4TXT("AUX 4"),
78 | USECAMERA(false),
79 | SENSORFILTERALPHA(0.03f),
80 | //KEEPSCREENON(true),
81 | PREVENTEXITWHENFLYING(true),
82 | ROLLPITCHLIMIT(250),
83 | SSID("");
84 |
85 | private String value;
86 | private Boolean bValue;
87 | private Float fValue;
88 | private Integer iValue;
89 |
90 | SettingsConstants(String value) {
91 | this.value = value;
92 | }
93 | SettingsConstants(boolean value) {
94 | this(value + "");
95 | this.bValue = value;
96 | }
97 | SettingsConstants(float value) {
98 | this(value + "");
99 | this.fValue = value;
100 | }
101 | SettingsConstants(int value) {
102 | this(value + "");
103 | this.iValue = value;
104 | }
105 |
106 | public String DefaultS() {
107 | return value;
108 | }
109 | public boolean DefaultB() {
110 | return bValue;
111 | }
112 | public float DefaultF() {
113 | return fValue;
114 | }
115 | public int DefaultI() {
116 | return iValue;
117 | }
118 |
119 | public boolean validate(Object newValue) {
120 | if(bValue != null) { //Object should be a boolean
121 | return Utilities.IsBoolean(newValue);
122 | }
123 | else if(fValue != null) {
124 | return Utilities.IsFloat(newValue);
125 | }
126 | else if(iValue != null) {
127 | return Utilities.IsInteger(newValue);
128 | }
129 | return true;
130 | }
131 | }
132 |
133 | //////////Constants///////////////////
134 | private static final String TAG = "App";
135 | public final static int SENSORSCHANGED = 9;
136 | public final int WifiConnectionStartDelay = 5000;
137 | public final int BluetoothConnectionStartDelay = 0;
138 | //Sounds
139 | public final int LOW_SIGNAL = 0;
140 | public final int LOW_PHONE_BATTERY = 0;
141 | public final int BLIP = 0;
142 | ///////End Constants//////////////////
143 |
144 | public boolean D = true;
145 | private boolean ManualMode = true;
146 | public boolean UsePhoneHeading = false;
147 | public int WriteRepeatDelayMillis = 40;
148 | public boolean AuxTextChanged = false;
149 | public String Status = "";
150 |
151 | /////////////Objects///////////
152 | public Sensors sensors;
153 | private Handler mHandler;
154 |
155 | public TTS tts;
156 | public SoundManager soundManager;
157 | public VarioSoundClass varioSoundClass;
158 |
159 | public Communication commMW;
160 | public MultirotorData protocol;
161 | private SharedPreferences prefs;
162 | private Editor prefsEditor;
163 | private RepeatTimer signalStrengthTimer = new RepeatTimer(5000);
164 | /////////End Objects/////////////
165 |
166 | public void SetHandler(Handler mHandler) {
167 | this.mHandler = mHandler;
168 | }
169 |
170 | @Override
171 | public void onCreate() {
172 | PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
173 | prefs = PreferenceManager.getDefaultSharedPreferences(this);
174 | prefsEditor = prefs.edit();
175 |
176 | sensors = new Sensors(getApplicationContext(), this);
177 | Init();
178 |
179 | tts = new TTS(getApplicationContext());
180 |
181 | varioSoundClass = new VarioSoundClass();
182 | }
183 |
184 | protected void Init() {
185 | ReadSettings();
186 | prepareSounds();
187 | }
188 | private void prepareSounds() {
189 | soundManager = new SoundManager(getApplicationContext());
190 | /*soundManager.addSound(LOW_SIGNAL, R.raw.lowSignal);
191 | soundManager.addSound(LOW_PHONE_BATTERY, R.raw.lowPhoneBattery);
192 | soundManager.addSound(BLIP, R.raw.blip);*///TODO
193 | }
194 | public void ReadSettings() {
195 | LowSignalThreshold = Integer.parseInt(prefs.getString(LOWSIGNALTHRESHOLD.toString(), LOWSIGNALTHRESHOLD.DefaultS()));
196 | TextToSpeach = prefs.getBoolean(TEXTTOSPEACH.toString(), TEXTTOSPEACH.DefaultB());
197 | RefreshRate = Integer.parseInt(prefs.getString(REFRESHRATE.toString(), REFRESHRATE.DefaultS()));
198 | UIDebug = prefs.getBoolean(UIDEBUG.toString(), UIDEBUG.DefaultB());
199 | TrimRoll = Integer.parseInt(prefs.getString(TRIMROLL.toString(), TRIMROLL.DefaultS()));
200 | TrimPitch = Integer.parseInt(prefs.getString(TRIMPITCH.toString(), TRIMPITCH.DefaultS()));
201 | ThrottleResolution = Integer.parseInt(prefs.getString(THROTTLERESOLUTION.toString(), THROTTLERESOLUTION.DefaultS()));
202 | BaudRate = Integer.parseInt(prefs.getString(BAUDRATE.toString(), BAUDRATE.DefaultS()));
203 | IpAddress = prefs.getString(IPADDRESS.toString(), IPADDRESS.DefaultS());
204 | IpPort = Integer.parseInt(prefs.getString(IPPORT.toString(), IPPORT.DefaultS()));
205 |
206 | Aux1Txt = prefs.getString(AUX1TXT.toString(), AUX1TXT.DefaultS());
207 | Aux2Txt = prefs.getString(AUX2TXT.toString(), AUX2TXT.DefaultS());
208 | Aux3Txt = prefs.getString(AUX3TXT.toString(), AUX3TXT.DefaultS());
209 | Aux4Txt = prefs.getString(AUX4TXT.toString(), AUX4TXT.DefaultS());
210 | AuxTextChanged = true;
211 |
212 | UseCamera = prefs.getBoolean(USECAMERA.toString(), USECAMERA.DefaultB());
213 | PreventExitWhenFlying = prefs.getBoolean(PREVENTEXITWHENFLYING.toString(), PREVENTEXITWHENFLYING.DefaultB());
214 | RollPitchLimit = Integer.parseInt(prefs.getString(ROLLPITCHLIMIT.toString(), ROLLPITCHLIMIT.DefaultS()));
215 | ssid = prefs.getString(SSID.toString(), SSID.DefaultS());
216 |
217 | sensors.setFilter(Float.parseFloat(prefs.getString(SENSORFILTERALPHA.toString(), SENSORFILTERALPHA.DefaultS())));
218 | comMode = CommunicationMode.valueOf(prefs.getString("comMode", "Bluetooth").toUpperCase(Locale.US));
219 | updateComMode();
220 | }
221 |
222 | @SuppressLint("NewApi")
223 | public void SaveSettings() {
224 | prefsEditor.putString(LOWSIGNALTHRESHOLD.toString(), LowSignalThreshold + "");
225 | prefsEditor.putBoolean(TEXTTOSPEACH.toString(), TextToSpeach);
226 | prefsEditor.putBoolean(UIDEBUG.toString(), UIDebug);
227 | prefsEditor.putString(REFRESHRATE.toString(), RefreshRate + "");
228 | prefsEditor.putString(TRIMROLL.toString(), TrimRoll + "");
229 | prefsEditor.putString(TRIMPITCH.toString(), TrimPitch + "");
230 | prefsEditor.putString(THROTTLERESOLUTION.toString(), ThrottleResolution + "");
231 | prefsEditor.putString(BAUDRATE.toString(), BaudRate + "");
232 | prefsEditor.putString(IPADDRESS.toString(), IpAddress);
233 | prefsEditor.putString(IPPORT.toString(), IpPort + "");
234 |
235 | prefsEditor.putString(AUX1TXT.toString(), Aux1Txt);
236 | prefsEditor.putString(AUX2TXT.toString(), Aux2Txt);
237 | prefsEditor.putString(AUX3TXT.toString(), Aux3Txt);
238 | prefsEditor.putString(AUX4TXT.toString(), Aux4Txt);
239 |
240 | prefsEditor.putBoolean(USECAMERA.toString(), UseCamera);
241 | prefsEditor.putBoolean(PREVENTEXITWHENFLYING.toString(), PreventExitWhenFlying);
242 | prefsEditor.putString(ROLLPITCHLIMIT.toString(), RollPitchLimit + "");
243 | prefsEditor.putString(SSID.toString(), ssid);
244 |
245 | prefsEditor.putString(SENSORFILTERALPHA.toString(), SensorFilterAlpha + "");
246 | //comMode = CommunicationMode.valueOf(prefs.getString("comMode", "Bluetooth").toUpperCase(Locale.US));
247 |
248 | if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD)
249 | prefsEditor.apply();
250 | else
251 | prefsEditor.commit();
252 | }
253 | public void FrequentTasks() {
254 | if(commMW.Connected) {
255 | if(signalStrengthTimer.isTime()) {
256 | signalStrengthTimer.reset();
257 | int signalStrength = commMW.getStrength();
258 | if(signalStrength != 0 && signalStrength < LowSignalThreshold) {
259 | Say("Low Signal " + signalStrength);
260 | }
261 | }
262 |
263 | }
264 | //TODO check low phone battery
265 | }
266 | protected void updateComMode() {
267 | if(commMW != null && commMW.getMode() == comMode) return;
268 |
269 | if (commMW != null) commMW.Close();
270 |
271 | switch (comMode) {
272 | case BLUETOOTH:
273 | commMW = new Bluetooth(getApplicationContext());
274 | WriteRepeatDelayMillis = 40;
275 | break;
276 | case WIFI:
277 | commMW = new Wifi(getApplicationContext());
278 | WriteRepeatDelayMillis = 20;
279 | break;
280 | }
281 | if (mHandler != null) commMW.SetHandler(mHandler);
282 | SelectProtocol();
283 | }
284 |
285 | public void SelectProtocol() {
286 | if(protocol != null) protocol.stop();
287 |
288 | protocol = new MultiWii230(commMW);
289 | }
290 |
291 | public boolean getManualMode() {
292 | return ManualMode;
293 | }
294 |
295 | public void setManualModeOn(boolean ManualMode) {
296 | this.ManualMode = ManualMode;
297 | Say(ManualMode ? "Manual" : "Automatic");
298 | }
299 |
300 | public void Say(String text) {
301 | if (TextToSpeach) tts.Speak(text);
302 | }
303 | public void onResume() {
304 | ReadSettings();this.sensors.start();
305 | }
306 | public void onPause() {
307 | this.SaveSettings();
308 | this.sensors.stop();
309 | }
310 | public void stop() {
311 | if(protocol != null) protocol.stop();
312 | if (commMW != null) commMW.Close();
313 | }
314 |
315 | @Override
316 | public void onTerminate() {
317 | stop();
318 | }
319 |
320 | @Override
321 | public void onSensorsStateChangeMagAcc() {
322 | if(mHandler != null) mHandler.sendEmptyMessage(SENSORSCHANGED);
323 | }
324 | }
325 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/multiwiiremote/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.multiwii.multiwiiremote;
2 |
3 |
4 | import view.joystick.DualJoystickView;
5 | import view.joystick.JoystickView;
6 | import com.multiwii.Utilities.Utilities;
7 | import com.multiwii.communication.DeviceListActivity;
8 | import android.os.Bundle;
9 | import android.app.Activity;
10 | import android.content.Intent;
11 | import android.util.Log;
12 | import android.view.KeyEvent;
13 | import android.view.MenuItem;
14 | import android.view.View;
15 | import android.widget.Button;
16 | import android.widget.CheckBox;
17 | import android.widget.TextView;
18 | import android.widget.ToggleButton;
19 | import static com.multiwii.multiwiiremote.RCSignals.*;
20 |
21 | public class MainActivity extends BaseActivity {
22 | private long requestStartTime;
23 | private boolean isReceived = true;
24 | private long lastRequestTime = 0;
25 |
26 | private enum InputMode {
27 | ACCELEROMETER, TOUCH
28 | }
29 |
30 | private InputMode inputMode = InputMode.TOUCH;
31 | private DualJoystickView dualJoystickView;
32 | private ToggleButton auxBtn[] = new ToggleButton[4];
33 | private TextView txtHeader;
34 | private TextView txtStatus;
35 | private TextView txtUIDebug;
36 | private long lastHeadingRefreshTime = 0;
37 | private int thisHeading = 0;
38 | private int mwcHeading = 0;
39 | private int lastValidateHeading =0;
40 | private String debugTextTemplate = "%sPhone Heading: %d\nMWC Heading:%d\nDelay: %dms";
41 | private long delayTime = 0;
42 | private long [] delayTimeRaw = new long[5];
43 | private boolean isDelayTimeAvailable = false;
44 | private int delayTimeIdx = 0;
45 | public CheckBox getChkUsePhoneHeading() {
46 | return chkUsePhoneHeading;
47 | }
48 |
49 | public void setChkUsePhoneHeading(CheckBox chkUsePhoneHeading) {
50 | this.chkUsePhoneHeading = chkUsePhoneHeading;
51 | }
52 |
53 | private CheckBox chkUsePhoneHeading;
54 | public RCSignals rc;
55 | // private byte timer = 0;
56 | // private Camera mCam;
57 | MainActivityEvents mEvents;
58 | private MainActivityCommunicationHandler mHandler;
59 |
60 | private final int BLUETOOTH_SEARCH_RETURN = 1;
61 | private final int SETTINGS_MODIFY = 2;
62 |
63 | @Override
64 | protected void onCreate(Bundle savedInstanceState) {
65 | super.onCreate(savedInstanceState);
66 | setContentView(R.layout.activity_main);
67 |
68 | //KeepScreenOn(app.KeepScreenOn);
69 | KeepScreenOn(true);
70 |
71 | rc = new RCSignals();
72 | // mCam = new Camera((MjpegView) this.findViewById(R.id.webcamView));
73 | mEvents = new MainActivityEvents(this);
74 | mHandler = new MainActivityCommunicationHandler(this);
75 |
76 | txtStatus = (TextView) findViewById(R.id.status);
77 | txtHeader = (TextView) findViewById(R.id.throttleView);
78 | txtUIDebug = (TextView) findViewById(R.id.debugTxt);
79 | for (int x = 0; x < auxBtn.length; x++)
80 | auxBtn[x] = (ToggleButton) findViewById(getResources().getIdentifier("aux" + (x + 1) + "Btn", "id", getPackageName()));
81 | dualJoystickView = (DualJoystickView) findViewById(R.id.DualJoystickView);
82 | chkUsePhoneHeading = (CheckBox) findViewById(R.id.chkUsePhoneHeading);
83 |
84 | Init();
85 | }
86 |
87 | private void Init() {
88 | app.SetHandler(mHandler); //App class will automatically bind to commMW
89 | app.setMainActivity(this);
90 | chkUsePhoneHeading.setOnCheckedChangeListener(mEvents.mCheckChangeListener);
91 |
92 | ((Button) findViewById(R.id.switchModes)).setOnClickListener(mEvents.mClickListener);
93 | //joystick.setOnJostickMovedListener(mEvents._listener);
94 | dualJoystickView.stickR.setOnJostickMovedListener(mEvents._listener);
95 | dualJoystickView.stickL.setOnJostickMovedListener(mEvents._throttleListener);
96 | dualJoystickView.stickL.setAutoReturnToCenter(false);
97 | dualJoystickView.stickL.setAutoReturnToMid(true);
98 | for (int x = 0; x < auxBtn.length; x++)
99 | auxBtn[x].setOnClickListener(mEvents.mClickListener);
100 | settingsModified();
101 | }
102 |
103 | public void FrequentTasks() {
104 | mHandler.sendEmptyMessage(7);
105 | //send RC signal
106 | if(app.commMW.Connected) {
107 | //Create payload TODO
108 | //new cycle begin if an ATTITUDE ACK is received or 300ms passed(package lost)
109 | long currentTime = System.currentTimeMillis();
110 | if(app.protocol.isIs_ATTITUDE_received() == true){
111 | app.protocol.setIs_ATTITUDE_received(false);
112 | delayTimeRaw[delayTimeIdx++] = app.protocol.attitudeReceivedTime - lastRequestTime;
113 | if(delayTimeIdx == delayTimeRaw.length){
114 | delayTimeIdx = 0;
115 | isDelayTimeAvailable = true;
116 | }
117 | if(isDelayTimeAvailable == true){
118 | long sum = 0;
119 | for(long i : delayTimeRaw){
120 | sum += i;
121 | }
122 | delayTime = sum / delayTimeRaw.length;
123 | }
124 | lastRequestTime = currentTime;
125 | app.protocol.SendRequestMSP_ATTITUDE();
126 | mwcHeading = app.protocol.head;
127 | }
128 | //we consider it as a package lost, resend package
129 | else if(currentTime - lastRequestTime > 300){
130 | app.protocol.SendRequestMSP_ATTITUDE();
131 | }
132 | app.protocol.SendRequestMSP_SET_RAW_RC(rc.get()); //TODO Check that delay isnt too big from other tasks
133 | if (chkUsePhoneHeading.isChecked()){
134 | //refresh heading in every 500 mili seconds
135 | if( currentTime - lastHeadingRefreshTime > 500 ){
136 | thisHeading = app.sensors.heading;
137 | app.protocol.SendRequestMSP_SET_HEAD(thisHeading);
138 | lastHeadingRefreshTime = currentTime;
139 | }
140 | }
141 | //SONG BO ADD BEGIN---------------------------------
142 |
143 | //data transmitted from MWC to Phone is processed in ProcessSerialData() in ConnectedThread
144 | // while(!app.protocol.is_SET_RAW_RC_received ){
145 | // app.protocol.ProcessSerialData(false);
146 | // if (app.protocol.is_SET_HEAD_received){
147 | // lastValidateHeading = thisHeading;
148 | // app.protocol.is_SET_HEAD_received = false;
149 | // }
150 | // delayTime = System.currentTimeMillis() - requestStartTime;
151 | // }
152 | // app.protocol.is_SET_RAW_RC_received = false;
153 | //SONG BO ADD END
154 | }
155 | app.FrequentTasks();
156 | }
157 |
158 | public void setStatus(String status) {
159 | this.txtStatus.setText(status);
160 | app.Status = status;
161 | }
162 |
163 | @Override
164 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
165 | super.onActivityResult(requestCode, resultCode, data);
166 | switch (requestCode) {
167 | case BLUETOOTH_SEARCH_RETURN:
168 | if (resultCode == Activity.RESULT_OK) {
169 | String address = data.getExtras().getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
170 | app.protocol.Connect(address, app.BaudRate, app.BluetoothConnectionStartDelay);
171 | }
172 | break;
173 | case SETTINGS_MODIFY:
174 | settingsModified();
175 | break;
176 | }
177 | }
178 | private void settingsModified() {
179 | rc.ThrottleResolution = app.ThrottleResolution;
180 | rc.TrimRoll = app.TrimRoll;
181 | rc.TrimPitch = app.TrimPitch;
182 | rc.RollPitchLimit = app.RollPitchLimit;
183 |
184 | if (app.AuxTextChanged) {
185 | setAuxbtnTxt(auxBtn[0], app.Aux1Txt);
186 | setAuxbtnTxt(auxBtn[1], app.Aux2Txt);
187 | setAuxbtnTxt(auxBtn[2], app.Aux3Txt);
188 | setAuxbtnTxt(auxBtn[3], app.Aux4Txt);
189 | app.AuxTextChanged = false;
190 | }
191 | setStatus("Ready " + app.comMode.toString());
192 | }
193 | private void setAuxbtnTxt(ToggleButton mButton, String text) {
194 | mButton.setText(text);
195 | mButton.setTextOn(text);
196 | mButton.setTextOff(text);
197 | }
198 | public void Connect() {
199 | switch (app.comMode) {
200 | case BLUETOOTH:
201 | Intent searchBtDevices = new Intent(this, DeviceListActivity.class);
202 | startActivityForResult(searchBtDevices, BLUETOOTH_SEARCH_RETURN);
203 | break;
204 | case WIFI:
205 | app.protocol.Connect(app.IpAddress, app.IpPort, app.WifiConnectionStartDelay);
206 | break;
207 | }
208 | }
209 | public void UpdateUI() {
210 | txtHeader.setText(rc.adjustMode.getValue() + rc.get(rc.adjustMode.getId()));
211 | txtUIDebug.setText(app.UIDebug ? String.format(debugTextTemplate, rc.toStringNoThrottle(), app.sensors.heading, mwcHeading, delayTime) : "");
212 | txtStatus.setText(app.Status);
213 | }
214 |
215 | // int requests[] = new int[] { MultirotorData.MSP_DEBUG,
216 | // MultirotorData.MSP_ALTITUDE, MultirotorData.MSP_RC };
217 | public void onSensorsStateChangeRotate() {
218 | if (inputMode == InputMode.ACCELEROMETER) {
219 | float xCoordinate = (float) Utilities.mapCons(-app.sensors.pitch,
220 | app.sensors.getMinValue(),
221 | app.sensors.getMaxValue(),
222 | -dualJoystickView.stickR.getMovementRange()/2, dualJoystickView.stickR.getMovementRange()/2);
223 | float yCoordinate = (float) Utilities.mapCons(-app.sensors.roll,
224 | app.sensors.getMinValue(),
225 | app.sensors.getMaxValue(),
226 | -dualJoystickView.stickR.getMovementRange()/2, dualJoystickView.stickR.getMovementRange()/2);
227 | dualJoystickView.stickR.setCoordinates(xCoordinate, yCoordinate);
228 | }
229 | }
230 |
231 | public void aux1_Click(View v) {
232 | // Replaced with When Throttle >= 1030
233 | rc.set(AUX1, ((ToggleButton) v).isChecked());
234 | }
235 |
236 | public void aux2_Click(View v) {
237 | rc.set(AUX2, ((ToggleButton) v).isChecked());
238 | }
239 |
240 | public void aux3_Click(View v) {
241 | rc.set(AUX3, ((ToggleButton) v).isChecked());
242 | }
243 |
244 | public void aux4_Click(View v) {
245 | rc.set(AUX4, ((ToggleButton) v).isChecked());
246 | }
247 |
248 | @Override
249 | protected void onStop() {
250 | super.onStop();
251 | app.stop();
252 | }
253 | // ///////////////////Menu///////////////////
254 | @Override
255 | public boolean onOptionsItemSelected(MenuItem item) {
256 | switch (item.getItemId()) {
257 | case R.id.connect:
258 | Connect();
259 | break;
260 | case R.id.accelOn:
261 | if (!app.sensors.isRotateSensorSupported())
262 | Utilities.showToast("Sorry, your device does not have an accelerometer", this);
263 | else {
264 | switch (inputMode) {
265 | case TOUCH:
266 | inputMode = InputMode.ACCELEROMETER;
267 | break;
268 | case ACCELEROMETER:
269 | inputMode = InputMode.TOUCH;
270 | dualJoystickView.stickR.returnHandleToCenter();
271 | break;
272 | }
273 | }
274 | break;
275 | case R.id.menu_settings:
276 | if (rc.isFlying()) {
277 | Utilities.showToast(
278 | "Set throttle under 1100 to access settings", this);
279 | } else {
280 | this.startActivityForResult(new Intent(this, Settings.class), SETTINGS_MODIFY);
281 | }
282 | break;
283 | }
284 | return super.onContextItemSelected(item);
285 | }
286 |
287 | // /////////////////////////////End Menu/////////////////////////////
288 | @Override
289 | public boolean dispatchKeyEvent(KeyEvent event) {
290 | if(app.PreventExitWhenFlying && rc.isFlying() && (event.getKeyCode() == KeyEvent.KEYCODE_BACK || event.getKeyCode() == KeyEvent.KEYCODE_APP_SWITCH || event.getKeyCode() == KeyEvent.KEYCODE_HOME))
291 | {
292 | Utilities.showToast("Detected flying. Please put throttle under 1100.", this);
293 | return true;
294 | }
295 | if (event.getAction() == KeyEvent.ACTION_DOWN)
296 | switch (event.getKeyCode()) {
297 | case KeyEvent.KEYCODE_VOLUME_UP:
298 | rc.adjustRcValue(-1);
299 | return true;
300 | case KeyEvent.KEYCODE_VOLUME_DOWN:
301 | rc.adjustRcValue(1);
302 | return true;
303 | case KeyEvent.KEYCODE_SEARCH:
304 | app.setManualModeOn(!app.getManualMode());
305 | return true;
306 | }
307 | return super.dispatchKeyEvent(event);
308 | }
309 | }
310 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/com/multiwii/Utilities/Sensors.java:
--------------------------------------------------------------------------------
1 | /* MultiWii EZ-GUI
2 | Copyright (C) <2012> Bartosz Szczygiel (eziosoft)
3 |
4 | This program is free software: you can redistribute it and/or modify
5 | it under the terms of the GNU General Public License as published by
6 | the Free Software Foundation, either version 3 of the License, or
7 | (at your option) any later version.
8 |
9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | GNU General Public License for more details.
13 |
14 | You should have received a copy of the GNU General Public License
15 | along with this program. If not, see .
16 | */
17 | package com.multiwii.Utilities;
18 |
19 | import java.lang.reflect.Method;
20 | import java.util.Iterator;
21 |
22 | //import com.google.android.gms.maps.model.LatLng;
23 |
24 | import android.content.Context;
25 | import android.hardware.GeomagneticField;
26 | import android.hardware.Sensor;
27 | import android.hardware.SensorEvent;
28 | import android.hardware.SensorEventListener;
29 | import android.hardware.SensorManager;
30 | import android.location.Criteria;
31 | import android.location.GpsSatellite;
32 | import android.location.GpsStatus;
33 | import android.location.Location;
34 | import android.location.LocationListener;
35 | import android.location.LocationManager;
36 | import android.os.Bundle;
37 | import android.os.Handler;
38 | import android.provider.Settings;
39 | import android.util.Log;
40 | import android.widget.Toast;
41 |
42 | import com.multiwii.multiwiiremote.App;
43 |
44 | public class Sensors implements LocationListener {
45 |
46 | private final App app;
47 | private MagAccListener mMagAccListener = null;
48 | private GPSListener mGPSListener = null;
49 |
50 | Location location, oldLocation;
51 |
52 | boolean useFilter = true;
53 | LowPassFilter filterYaw = new LowPassFilter(0.03f);
54 | LowPassFilter filterPitch = new LowPassFilter(0.03f);
55 | LowPassFilter filterRoll = new LowPassFilter(0.03f);
56 |
57 | private LocationManager locationManager;
58 | private String provider;
59 | GeomagneticField geoField;
60 |
61 | public int PhoneNumSat = 0;
62 | public double PhoneLatitude = 0;
63 | public double PhoneLongitude = 0;
64 | public double PhoneAltitude = 0;
65 | public double PhoneSpeed = 0;
66 | public int PhoneFix = 0;
67 | public float PhoneAccuracy = 0;
68 | public float Declination = 0;
69 |
70 | //public LatLng MapCurrentPosition = new LatLng(0, 0);
71 |
72 | SensorManager m_sensorManager;
73 | Sensor rotateSensor;
74 | private float[] m_rotationMatrix = new float[9];
75 | private float[] m_orientation = new float[3];
76 |
77 | public float pitch = 0.f;
78 | public int heading = 0;
79 | public float roll = 0.f;
80 |
81 | private Context context;
82 |
83 | String mocLocationProvider;
84 | public boolean MockLocationWorking = false;
85 |
86 | public float getMaxValue() {
87 | return maxValue;
88 | }
89 |
90 | public float getMinValue() {
91 | return minValue;
92 | }
93 |
94 | private float minValue = 0;
95 | private float maxValue = 0;
96 | private Handler mHandler;
97 | private SensorEventListener rotateListener;
98 |
99 | public boolean isRotateSensorSupported() {
100 | return m_sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null;
101 | }
102 |
103 | public interface MagAccListener {
104 |
105 | public void onSensorsStateChangeMagAcc();
106 |
107 | }
108 |
109 | public interface GPSListener {
110 |
111 | public void onSensorsStateGPSLocationChange();
112 |
113 | public void onSensorsStateGPSStatusChange();
114 | }
115 |
116 | public void registerListener(MagAccListener listener) {
117 | this.mMagAccListener = listener;
118 | }
119 |
120 | public void registerListener(GPSListener listener) {
121 | this.mGPSListener = listener;
122 | }
123 |
124 | public void initMOCKLocation() {
125 | mocLocationProvider = LocationManager.GPS_PROVIDER;
126 | locationManager.addTestProvider(mocLocationProvider, false, false, false, false, true, true, true, 0, 5);
127 | locationManager.setTestProviderEnabled(mocLocationProvider, true);
128 | MockLocationWorking = true;
129 | }
130 |
131 | public boolean isMockEnabled() {
132 | try {
133 | int mock_location = Settings.Secure.getInt(context.getContentResolver(), "mock_location");
134 | if (mock_location == 0) {
135 | try {
136 | Settings.Secure.putInt(context.getContentResolver(), "mock_location", 1);
137 | } catch (Exception ex) {
138 | }
139 | mock_location = Settings.Secure.getInt(context.getContentResolver(), "mock_location");
140 | }
141 |
142 | if (mock_location == 0) {
143 | Toast.makeText(context, "Turn on the mock locations in your Android settings", Toast.LENGTH_LONG).show();
144 | return false;
145 | } else {
146 | return true;
147 | }
148 |
149 | } catch (Exception ex) {
150 | ex.printStackTrace();
151 | }
152 |
153 | return false;
154 | }
155 |
156 | public void setMOCKLocation(double Latitude, double Longitude, float Altitude, float Heading, float speed) {
157 |
158 | Location mockLocation = new Location(mocLocationProvider); // a string
159 | mockLocation.setLatitude(Latitude); // double
160 | mockLocation.setLongitude(Longitude);
161 | mockLocation.setAltitude(Altitude);
162 | mockLocation.setTime(System.currentTimeMillis());
163 | mockLocation.setAccuracy(1);
164 | mockLocation.setBearing(Heading);
165 | mockLocation.setSpeed(speed * 0.01f);
166 |
167 | try {
168 | Method locationJellyBeanFixMethod = Location.class.getMethod("makeComplete");
169 | if (locationJellyBeanFixMethod != null) {
170 | locationJellyBeanFixMethod.invoke(mockLocation);
171 | }
172 | } catch (Exception e) {
173 | // TODO: handle exception
174 | }
175 |
176 | locationManager.setTestProviderLocation(mocLocationProvider, mockLocation);
177 |
178 | }
179 |
180 | public void ClearMOCKLocation() {
181 | if (mocLocationProvider != null) {
182 | Log.d("aaa", "ClearMOCKLocation");
183 |
184 | locationManager.clearTestProviderEnabled(mocLocationProvider);
185 | locationManager.clearTestProviderLocation(mocLocationProvider);
186 | locationManager.clearTestProviderStatus(mocLocationProvider);
187 | locationManager.removeTestProvider(mocLocationProvider);
188 | start();
189 | MockLocationWorking = false;
190 |
191 | }
192 | }
193 | public Sensors(Context applicationContext, final App app) {
194 | this.context = applicationContext;
195 | this.app = app;
196 | m_sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
197 | rotateSensor = m_sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
198 | //locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
199 | maxValue = (float) rotateSensor.getMaximumRange();
200 | minValue = -maxValue;
201 |
202 | //sensor listener
203 | rotateListener = new SensorEventListener() {
204 | private float []rotationMatrix = new float[9];
205 | private float []orientation = new float[3];
206 | @Override
207 | public void onSensorChanged(SensorEvent event) {
208 |
209 | m_sensorManager.getRotationMatrixFromVector(rotationMatrix, event.values);
210 | m_sensorManager.getOrientation(rotationMatrix, orientation);
211 | heading = (int)Math.toDegrees(orientation[0]);
212 | //calibrate mag with multiwii
213 | heading += 90;
214 | if(heading > 180){
215 | heading -= 360;
216 | }
217 |
218 | pitch = orientation[1]; //Pitch, rad
219 | roll = orientation[2]; //Roll, rad
220 | if(useFilter) {
221 | heading = filterYaw.lowPass(heading);
222 | pitch = filterPitch.lowPass(pitch);
223 | roll = filterRoll.lowPass(roll);
224 | }
225 | app.getMainActivity().onSensorsStateChangeRotate();
226 | }
227 |
228 | @Override
229 | public void onAccuracyChanged(Sensor sensor, int accuracy) {
230 |
231 | }
232 | };
233 |
234 |
235 | //Criteria criteria = new Criteria();
236 | // if (!app.D)
237 | //criteria.setAccuracy(Criteria.ACCURACY_FINE);
238 | //provider = locationManager.getBestProvider(criteria, false);
239 | //if(provider != null)
240 | //location = locationManager.getLastKnownLocation(provider);
241 | /*if (location != null) {
242 | geoField = new GeomagneticField(Double.valueOf(location.getLatitude()).floatValue(), Double.valueOf(location.getLongitude()).floatValue(), Double.valueOf(location.getAltitude()).floatValue(), System.currentTimeMillis());
243 | Declination = geoField.getDeclination();
244 |
245 | //MapCurrentPosition = new LatLng(location.getLatitude(), location.getLongitude());
246 |
247 | oldLocation = location;
248 |
249 | }
250 |
251 | locationManager.addGpsStatusListener(new GpsStatus.Listener() {
252 |
253 | @Override
254 | public void onGpsStatusChanged(int event) {
255 | if (event == GpsStatus.GPS_EVENT_SATELLITE_STATUS) {
256 | GpsStatus status = locationManager.getGpsStatus(null);
257 | Iterable sats = status.getSatellites();
258 | Iterator it = sats.iterator();
259 |
260 | PhoneNumSat = 0;
261 | while (it.hasNext()) {
262 |
263 | GpsSatellite oSat = (GpsSatellite) it.next();
264 | if (oSat.usedInFix())
265 | PhoneNumSat++;
266 | }
267 |
268 | }
269 | if (event == GpsStatus.GPS_EVENT_FIRST_FIX)
270 | PhoneFix = 1;
271 |
272 | if (mGPSListener != null)
273 | mGPSListener.onSensorsStateGPSStatusChange();
274 | }
275 | });*/
276 | }
277 |
278 |
279 | public void start() {
280 | //register rotate sensor listener
281 | if(this.app.getMainActivity().getChkUsePhoneHeading().isChecked()) {
282 | m_sensorManager.registerListener(rotateListener, rotateSensor, SensorManager.SENSOR_DELAY_FASTEST);
283 | }
284 | }
285 |
286 | // public void startMagACC() {
287 | // m_sensorManager.registerListener(this, m_sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_FASTEST);
288 | // }
289 | //
290 | // public void stopMagACC() {
291 | // m_sensorManager.unregisterListener(this);
292 | // }
293 |
294 | private void unregisterListeners() {
295 | //stopMagACC();
296 | mMagAccListener = null;
297 | mGPSListener = null;
298 | locationManager.removeUpdates(this);
299 | }
300 |
301 | public void stop() {
302 | m_sensorManager.unregisterListener(rotateListener);
303 | }
304 |
305 |
306 | private void computeOrientation() {
307 | if (mMagAccListener != null)
308 | mMagAccListener.onSensorsStateChangeMagAcc();
309 | }
310 |
311 | public void setFilter(float ALPHA) {
312 | if(ALPHA <= 0) {
313 | useFilter = ALPHA > 0;
314 | return;
315 | }
316 | if(ALPHA > 1)
317 | throw new ArithmeticException("Alpha must be between 0 and 1");
318 | filterYaw.setFilter(ALPHA);
319 | filterPitch.setFilter(ALPHA);
320 | filterRoll.setFilter(ALPHA);
321 | }
322 | @Override
323 | public void onLocationChanged(Location location) {
324 |
325 | oldLocation = this.location;
326 | this.location = location;
327 |
328 | PhoneLatitude = location.getLatitude();
329 | PhoneLongitude = location.getLongitude();
330 | PhoneAltitude = location.getAltitude();
331 | PhoneSpeed = location.getSpeed() * 100f;
332 | PhoneAccuracy = location.getAccuracy() * 100f;
333 |
334 | //MapCurrentPosition = new LatLng(location.getLatitude(), location.getLongitude());
335 |
336 | geoField = new GeomagneticField(Double.valueOf(location.getLatitude()).floatValue(), Double.valueOf(location.getLongitude()).floatValue(), Double.valueOf(location.getAltitude()).floatValue(), System.currentTimeMillis());
337 | Declination = geoField.getDeclination();
338 |
339 | if (mGPSListener != null)
340 | mGPSListener.onSensorsStateGPSLocationChange();
341 | }
342 |
343 | @Override
344 | public void onProviderDisabled(String provider) {
345 |
346 | }
347 |
348 | @Override
349 | public void onProviderEnabled(String provider) {
350 |
351 | }
352 |
353 | @Override
354 | public void onStatusChanged(String provider, int status, Bundle extras) {
355 |
356 | }
357 |
358 | /*public LatLng getNextPredictedLocationOnlineMap() {
359 | if (location != null && oldLocation != null) {
360 | int lat = (int) ((location.getLatitude() + (location.getLatitude() - oldLocation.getLatitude())));
361 | int lon = (int) ((location.getLongitude() + (location.getLongitude() - oldLocation.getLongitude())));
362 | return new LatLng(lat, lon);
363 | } else
364 | return new LatLng(0, 0);
365 |
366 | }*/
367 |
368 | }
369 |
--------------------------------------------------------------------------------
/MultiwiiRemote/src/view/joystick/JoystickView.java:
--------------------------------------------------------------------------------
1 | package view.joystick;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Color;
6 | import android.graphics.Paint;
7 | import android.util.AttributeSet;
8 | import android.util.Log;
9 | import android.view.HapticFeedbackConstants;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 |
13 | public class JoystickView extends View {
14 | public static final int INVALID_POINTER_ID = -1;
15 |
16 | // =========================================
17 | // Private Members
18 | // =========================================
19 | private final boolean D = false;
20 | String TAG = "JoystickView";
21 |
22 | private Paint dbgPaint1;
23 | private Paint dbgPaint2;
24 |
25 | private Paint bgPaint;
26 | private Paint handlePaint;
27 | private Paint bgPaint1;
28 | private Paint handlePaint1;
29 |
30 | private int innerPadding;
31 | private int bgRadius;
32 | private int handleRadius;
33 | private int movementRadius;
34 | private int handleInnerBoundaries;
35 |
36 | private JoystickMovedListener moveListener;
37 | private JoystickClickedListener clickListener;
38 |
39 | // # of pixels movement required between reporting to the listener
40 | private float moveResolution;
41 |
42 | private boolean yAxisInverted;
43 | private boolean autoReturnToCenter;
44 | private boolean autoReturnToMid;
45 |
46 | // Max range of movement in user coordinate system
47 | public final static int CONSTRAIN_BOX = 0;
48 | public final static int CONSTRAIN_CIRCLE = 1;
49 | private int movementConstraint;
50 | private float movementRange;
51 | private float maxMovementRange;
52 | private float minMovementRange;
53 |
54 | public final static int COORDINATE_CARTESIAN = 0; // Regular cartesian
55 | // coordinates
56 | public final static int COORDINATE_DIFFERENTIAL = 1; // Uses polar rotation
57 | // of 45 degrees to
58 | // calc differential
59 | // drive paramaters
60 | private int userCoordinateSystem;
61 |
62 | // Records touch pressure for click handling
63 | private float touchPressure;
64 | private boolean clicked;
65 | private float clickThreshold;
66 |
67 | // Last touch point in view coordinates
68 | private int pointerId = INVALID_POINTER_ID;
69 |
70 | public void setTouchY(float touchY) {
71 | this.touchY = touchY;
72 | }
73 |
74 | private float touchX, touchY;
75 |
76 | // Last reported position in view coordinates (allows different reporting
77 | // sensitivities)
78 | private float reportX, reportY;
79 |
80 | // Handle center in view coordinates
81 | private float handleX, handleY;
82 |
83 | // Center of the view in view coordinates
84 | private int cX, cY;
85 |
86 | // Size of the view in view coordinates
87 | @SuppressWarnings("unused")
88 | private int dimX, dimY;
89 |
90 | // Cartesian coordinates of last touch point - joystick center is (0,0)
91 | private int cartX, cartY;
92 |
93 | // Polar coordinates of the touch point from joystick center
94 | private double radial;
95 | private double angle;
96 |
97 | // User coordinates of last touch point
98 | private int userX, userY;
99 |
100 | // Offset co-ordinates (used when touch events are received from parent's
101 | // coordinate origin)
102 | private int offsetX;
103 | private int offsetY;
104 |
105 | private boolean isInit = true;
106 | // =========================================
107 | // Constructors
108 | // =========================================
109 |
110 | public JoystickView(Context context) {
111 | super(context);
112 | initJoystickView();
113 | }
114 |
115 | public JoystickView(Context context, AttributeSet attrs) {
116 | super(context, attrs);
117 | initJoystickView();
118 | }
119 |
120 | public JoystickView(Context context, AttributeSet attrs, int defStyle) {
121 | super(context, attrs, defStyle);
122 | initJoystickView();
123 | }
124 |
125 | // =========================================
126 | // Initialization
127 | // =========================================
128 |
129 | private void initJoystickView() {
130 | setFocusable(true);
131 |
132 | dbgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
133 | dbgPaint1.setColor(Color.RED);
134 | dbgPaint1.setAlpha(60);
135 | dbgPaint1.setStrokeWidth(1);
136 | dbgPaint1.setStyle(Paint.Style.STROKE);
137 |
138 | dbgPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
139 | dbgPaint2.setColor(Color.GRAY);
140 | dbgPaint2.setStrokeWidth(1);
141 | dbgPaint2.setStyle(Paint.Style.STROKE);
142 |
143 | bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
144 | bgPaint.setColor(Color.WHITE);
145 | bgPaint.setAlpha(140);
146 | bgPaint.setStrokeWidth(3);
147 | bgPaint.setStyle(Paint.Style.STROKE);
148 |
149 | bgPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
150 | bgPaint1.setColor(Color.GRAY);
151 | bgPaint1.setAlpha(80);
152 | bgPaint1.setStyle(Paint.Style.FILL);
153 |
154 | handlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
155 | handlePaint.setColor(Color.WHITE);
156 | handlePaint.setStrokeWidth(2);
157 | bgPaint.setAlpha(140);
158 | handlePaint.setStyle(Paint.Style.STROKE);
159 |
160 | handlePaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
161 | handlePaint1.setColor(Color.GRAY);
162 | handlePaint1.setAlpha(180);
163 | handlePaint1.setStyle(Paint.Style.FILL);
164 |
165 | innerPadding = 10;
166 |
167 | setMovementRange(500);
168 | setMoveResolution(1.0f);
169 | setClickThreshold(0.4f);
170 | setYAxisInverted(true);
171 | setUserCoordinateSystem(COORDINATE_CARTESIAN);
172 | setAutoReturnToCenter(true);
173 | setAutoReturnToMid(false);
174 |
175 |
176 | }
177 |
178 | public void setAutoReturnToMid(boolean b) {
179 | this.autoReturnToMid = b;
180 | }
181 |
182 | public boolean getAutoReturnToMid(){
183 | return this.autoReturnToMid;
184 | }
185 |
186 | public void setAutoReturnToCenter(boolean autoReturnToCenter) {
187 | this.autoReturnToCenter = autoReturnToCenter;
188 | }
189 |
190 | public boolean isAutoReturnToCenter() {
191 | return autoReturnToCenter;
192 | }
193 |
194 | public void setUserCoordinateSystem(int userCoordinateSystem) {
195 | if (userCoordinateSystem < COORDINATE_CARTESIAN
196 | || movementConstraint > COORDINATE_DIFFERENTIAL)
197 | Log.e(TAG, "invalid value for userCoordinateSystem");
198 | else
199 | this.userCoordinateSystem = userCoordinateSystem;
200 | }
201 |
202 | public int getUserCoordinateSystem() {
203 | return userCoordinateSystem;
204 | }
205 |
206 | public void setMovementConstraint(int movementConstraint) {
207 | if (movementConstraint < CONSTRAIN_BOX
208 | || movementConstraint > CONSTRAIN_CIRCLE)
209 | Log.e(TAG, "invalid value for movementConstraint");
210 | else
211 | this.movementConstraint = movementConstraint;
212 | }
213 |
214 | public int getMovementConstraint() {
215 | return movementConstraint;
216 | }
217 |
218 | public boolean isYAxisInverted() {
219 | return yAxisInverted;
220 | }
221 |
222 | public void setYAxisInverted(boolean yAxisInverted) {
223 | this.yAxisInverted = yAxisInverted;
224 | }
225 |
226 | /**
227 | * Set the pressure sensitivity for registering a click
228 | *
229 | * @param clickThreshold
230 | * threshold 0...1.0f inclusive. 0 will cause clicks to never be
231 | * reported, 1.0 is a very hard click
232 | */
233 | public void setClickThreshold(float clickThreshold) {
234 | if (clickThreshold < 0 || clickThreshold > 1.0f)
235 | Log.e(TAG, "clickThreshold must range from 0...1.0f inclusive");
236 | else
237 | this.clickThreshold = clickThreshold;
238 | }
239 |
240 | public float getClickThreshold() {
241 | return clickThreshold;
242 | }
243 |
244 | public void setMovementRange(float movementRange) {
245 | this.movementRange = movementRange;
246 | this.maxMovementRange = movementRange / 2;
247 | this.minMovementRange = -maxMovementRange;
248 | }
249 |
250 | public float getMovementRange() {
251 | return movementRange;
252 | }
253 |
254 | public void setMoveResolution(float moveResolution) {
255 | this.moveResolution = moveResolution;
256 | }
257 |
258 | public float getMoveResolution() {
259 | return moveResolution;
260 | }
261 |
262 | public float getMoveResolutionMax() {
263 | return this.maxMovementRange;
264 | }
265 |
266 | public float getMoveResolutionMin() {
267 | return this.minMovementRange;
268 | }
269 |
270 | // =========================================
271 | // Public Methods
272 | // =========================================
273 |
274 | public void setOnJostickMovedListener(JoystickMovedListener listener) {
275 | this.moveListener = listener;
276 | }
277 |
278 | public void setOnJostickClickedListener(JoystickClickedListener listener) {
279 | this.clickListener = listener;
280 | }
281 |
282 | // =========================================
283 | // Drawing Functionality
284 | // =========================================
285 |
286 | @Override
287 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
288 | // Here we make sure that we have a perfect circle
289 | int measuredWidth = measure(widthMeasureSpec);
290 | int measuredHeight = measure(heightMeasureSpec);
291 | setMeasuredDimension(measuredWidth, measuredHeight);
292 | }
293 |
294 |
295 | @Override
296 | protected void onLayout(boolean changed, int left, int top, int right,
297 | int bottom) {
298 | super.onLayout(changed, left, top, right, bottom);
299 |
300 | int d = Math.min(getMeasuredWidth(), getMeasuredHeight());
301 |
302 | dimX = d;
303 | dimY = d;
304 |
305 | cX = d / 2;
306 | cY = d / 2;
307 |
308 | bgRadius = dimX / 2 - innerPadding;
309 | handleRadius = (int) (d * 0.25);
310 | handleInnerBoundaries = handleRadius;
311 | movementRadius = Math.min(cX, cY) - handleInnerBoundaries;
312 | if(isInit == true && autoReturnToMid == true){
313 | isInit = false;
314 | touchY = movementRadius;
315 | }
316 | }
317 |
318 | private int measure(int measureSpec) {
319 | int result = 0;
320 | // Decode the measurement specifications.
321 | int specMode = MeasureSpec.getMode(measureSpec);
322 | int specSize = MeasureSpec.getSize(measureSpec);
323 | if (specMode == MeasureSpec.UNSPECIFIED) {
324 | // Return a default size of 200 if no bounds are specified.
325 | result = 200;
326 | } else {
327 | // As you want to fill the available space
328 | // always return the full available bounds.
329 | result = specSize;
330 | }
331 | return result;
332 | }
333 |
334 | @Override
335 | protected void onDraw(Canvas canvas) {
336 | canvas.save();
337 | // Draw the background
338 | canvas.drawCircle(cX, cY, bgRadius, bgPaint);
339 | canvas.drawCircle(cX, cY, bgRadius, bgPaint1);
340 |
341 | // Draw the handle
342 | handleX = touchX + cX;
343 | handleY = touchY + cY;
344 | canvas.drawCircle(handleX, handleY, handleRadius, handlePaint);
345 | canvas.drawCircle(handleX, handleY, handleRadius, handlePaint1);
346 |
347 | if (D) {
348 | canvas.drawRect(1, 1, getMeasuredWidth() - 1,
349 | getMeasuredHeight() - 1, dbgPaint1);
350 |
351 | canvas.drawCircle(handleX, handleY, 3, dbgPaint1);
352 |
353 | if (movementConstraint == CONSTRAIN_CIRCLE) {
354 | canvas.drawCircle(cX, cY, this.movementRadius, dbgPaint1);
355 | } else {
356 | canvas.drawRect(cX - movementRadius, cY - movementRadius, cX
357 | + movementRadius, cY + movementRadius, dbgPaint1);
358 | }
359 |
360 | // Origin to touch point
361 | canvas.drawLine(cX, cY, handleX, handleY, dbgPaint2);
362 |
363 | int baseY = (int) (touchY < 0 ? cY + handleRadius : cY
364 | - handleRadius);
365 | canvas.drawText(
366 | String.format("%s (%.0f,%.0f)", TAG, touchX, touchY),
367 | handleX - 20, baseY - 7, dbgPaint2);
368 | canvas.drawText(
369 | "("
370 | + String.format("%.0f, %.1f", radial,
371 | angle * 57.2957795) + (char) 0x00B0 + ")",
372 | handleX - 20, baseY + 15, dbgPaint2);
373 | }
374 |
375 | // Log.d(TAG, String.format("touch(%f,%f)", touchX, touchY));
376 | // Log.d(TAG, String.format("onDraw(%.1f,%.1f)\n\n", handleX, handleY));
377 | canvas.restore();
378 | }
379 |
380 | // Constrain touch within a box
381 | private void constrainBox() {
382 | touchX = Math.max(Math.min(touchX, movementRadius), -movementRadius);
383 | touchY = Math.max(Math.min(touchY, movementRadius), -movementRadius);
384 | }
385 |
386 | // Constrain touch within a circle
387 | private void constrainCircle() {
388 | float diffX = touchX;
389 | float diffY = touchY;
390 | double radial = Math.sqrt((diffX * diffX) + (diffY * diffY));
391 | if (radial > movementRadius) {
392 | touchX = (int) ((diffX / radial) * movementRadius);
393 | touchY = (int) ((diffY / radial) * movementRadius);
394 | }
395 | }
396 |
397 | public void setPointerId(int id) {
398 | this.pointerId = id;
399 | }
400 |
401 | public int getPointerId() {
402 | return pointerId;
403 | }
404 |
405 | @Override
406 | public boolean onTouchEvent(MotionEvent ev) {
407 | final int action = ev.getAction();
408 | switch (action & MotionEvent.ACTION_MASK) {
409 | case MotionEvent.ACTION_MOVE: {
410 | return processMoveEvent(ev);
411 | }
412 | case MotionEvent.ACTION_CANCEL:
413 | case MotionEvent.ACTION_UP: {
414 |
415 | if (pointerId != INVALID_POINTER_ID) {
416 | // Log.d(TAG, "ACTION_UP");
417 | returnHandleToCenter();
418 | setPointerId(INVALID_POINTER_ID);
419 | }
420 | break;
421 | }
422 | case MotionEvent.ACTION_POINTER_UP: {
423 |
424 | if (pointerId != INVALID_POINTER_ID) {
425 | final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
426 | final int pointerId = ev.getPointerId(pointerIndex);
427 | if (pointerId == this.pointerId) {
428 | // Log.d(TAG, "ACTION_POINTER_UP: " + pointerId);
429 | returnHandleToCenter();
430 | setPointerId(INVALID_POINTER_ID);
431 | return true;
432 | }
433 | }
434 | break;
435 | }
436 | case MotionEvent.ACTION_DOWN: {
437 | if (pointerId == INVALID_POINTER_ID) {
438 | int x = (int) ev.getX();
439 | if (x >= offsetX && x < offsetX + dimX ) {
440 | setPointerId(ev.getPointerId(0));
441 | return true;
442 | }
443 | }
444 | break;
445 | }
446 | case MotionEvent.ACTION_POINTER_DOWN: {
447 | // Log.d("JoyStickView", "ACTION_POINTER_MOVE");
448 |
449 | if (pointerId == INVALID_POINTER_ID) {
450 | final int pointerIndex = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
451 | final int pointerId = ev.getPointerId(pointerIndex);
452 | int x = (int) ev.getX(pointerId);
453 | if (x >= offsetX && x < offsetX + dimX) {
454 | // Log.d(TAG, "ACTION_POINTER_DOWN: " + pointerId);
455 | setPointerId(pointerId);
456 | return true;
457 | }
458 | }
459 | break;
460 | }
461 | }
462 | return false;
463 | }
464 |
465 | private boolean processMoveEvent(MotionEvent ev) {
466 | if (pointerId != INVALID_POINTER_ID) {
467 | final int pointerIndex = ev.findPointerIndex(pointerId);
468 | // Translate touch position to center of view
469 | float x = ev.getX(pointerIndex);
470 | touchX = x - cX - offsetX;
471 | float y = ev.getY(pointerIndex);
472 | touchY = y - cY - offsetY;
473 |
474 | // Log.d(TAG,
475 | // String.format("ACTION_MOVE: (%03.0f, %03.0f) => (%03.0f, %03.0f)",
476 | // x, y, touchX, touchY));
477 |
478 | reportOnMoved();
479 | invalidate();
480 |
481 | touchPressure = ev.getPressure(pointerIndex);
482 | reportOnPressure();
483 |
484 | return true;
485 | }
486 | return false;
487 | }
488 |
489 | private void reportOnMoved() {
490 | if (movementConstraint == CONSTRAIN_CIRCLE)
491 | constrainCircle();
492 | else
493 | constrainBox();
494 |
495 | calcUserCoordinates();
496 |
497 | if (moveListener != null) {
498 | boolean rx = Math.abs(touchX - reportX) >= moveResolution;
499 | boolean ry = Math.abs(touchY - reportY) >= moveResolution;
500 | if (rx || ry) {
501 | this.reportX = touchX;
502 | this.reportY = touchY;
503 |
504 | // Log.d(TAG, String.format("moveListener.OnMoved(%d,%d)",
505 | // (int)userX, (int)userY));
506 | moveListener.OnMoved(userX, userY);
507 | }
508 | }
509 | }
510 |
511 | private void calcUserCoordinates() {
512 | // First convert to cartesian coordinates
513 | cartX = (int) (touchX / movementRadius * movementRange);
514 | cartY = (int) (touchY / movementRadius * movementRange);
515 |
516 | radial = Math.sqrt((cartX * cartX) + (cartY * cartY));
517 | angle = Math.atan2(cartY, cartX);
518 |
519 | // Invert Y axis if requested
520 | if (!yAxisInverted)
521 | cartY *= -1;
522 |
523 | if (userCoordinateSystem == COORDINATE_CARTESIAN) {
524 | userX = cartX;
525 | userY = cartY;
526 | } else if (userCoordinateSystem == COORDINATE_DIFFERENTIAL) {
527 | userX = cartY + cartX / 4;
528 | userY = cartY - cartX / 4;
529 |
530 | if (userX < -movementRange)
531 | userX = (int) -movementRange;
532 | if (userX > movementRange)
533 | userX = (int) movementRange;
534 |
535 | if (userY < -movementRange)
536 | userY = (int) -movementRange;
537 | if (userY > movementRange)
538 | userY = (int) movementRange;
539 | }
540 |
541 | }
542 |
543 | // Simple pressure click
544 | private void reportOnPressure() {
545 | // Log.d(TAG, String.format("touchPressure=%.2f", this.touchPressure));
546 | if (clickListener != null) {
547 | if (clicked && touchPressure < clickThreshold) {
548 | clickListener.OnReleased();
549 | this.clicked = false;
550 | // Log.d(TAG, "reset click");
551 | invalidate();
552 | } else if (!clicked && touchPressure >= clickThreshold) {
553 | clicked = true;
554 | clickListener.OnClicked();
555 | // Log.d(TAG, "click");
556 | invalidate();
557 | performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
558 | }
559 | }
560 | }
561 |
562 | public void setCoordinates(float touchX, float touchY) {
563 | if (!this.isPressed()) {
564 | this.touchX = touchX;
565 | this.touchY = touchY;
566 | reportOnMoved();
567 | invalidate();
568 | }
569 | }
570 | public void returnHandleToMid(){
571 | final int numberOfFrames = 5;
572 | final double intervalsX = (0 - touchX) / numberOfFrames;
573 | for (int i = 0; i < numberOfFrames; i++) {
574 | final int j = i;
575 | postDelayed(new Runnable() {
576 | @Override
577 | public void run() {
578 | touchX += intervalsX;
579 |
580 | reportOnMoved();
581 | invalidate();
582 |
583 | if (moveListener != null && j == numberOfFrames - 1) {
584 | moveListener.OnReturnedToCenter();
585 | }
586 | }
587 | }, i * 40);
588 | }
589 |
590 | if (moveListener != null) {
591 | moveListener.OnReleased();
592 | }
593 | }
594 | public void returnHandleToCenter() {
595 | if (autoReturnToCenter) {
596 | final int numberOfFrames = 5;
597 | final double intervalsX = (0 - touchX) / numberOfFrames;
598 | final double intervalsY = (0 - touchY) / numberOfFrames;
599 |
600 | for (int i = 0; i < numberOfFrames; i++) {
601 | final int j = i;
602 | postDelayed(new Runnable() {
603 | @Override
604 | public void run() {
605 | touchX += intervalsX;
606 | touchY += intervalsY;
607 |
608 | reportOnMoved();
609 | invalidate();
610 |
611 | if (moveListener != null && j == numberOfFrames - 1) {
612 | moveListener.OnReturnedToCenter();
613 | }
614 | }
615 | }, i * 40);
616 | }
617 |
618 | if (moveListener != null) {
619 | moveListener.OnReleased();
620 | }
621 | }
622 | else if(autoReturnToMid){
623 | this.returnHandleToMid();
624 | }
625 | }
626 |
627 | public void setTouchOffset(int x, int y) {
628 | offsetX = x;
629 | offsetY = y;
630 | }
631 |
632 | public float getTouchY() {
633 | return this.touchY;
634 | }
635 | }
636 |
--------------------------------------------------------------------------------