/* MultiWii EZ-GUI Copyright (C) <2012> Bartosz Szczygiel (eziosoft) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.ezio.multiwii.app; import java.util.Locale; import android.app.Activity; import android.app.AlarmManager; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Application; import android.app.Dialog; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.content.res.Configuration; import android.net.Uri; import android.preference.PreferenceManager; import android.util.Log; import android.view.View; import android.widget.Toast; import com.ezio.multiwii.R; import com.ezio.multiwii.Main.MainMultiWiiActivity; import com.ezio.multiwii.frsky.FrskyProtocol; import com.ezio.multiwii.helpers.Functions; import com.ezio.multiwii.helpers.Notifications; import com.ezio.multiwii.helpers.Sensors; import com.ezio.multiwii.helpers.SoundManager; import com.ezio.multiwii.helpers.TTS; import com.ezio.multiwii.helpers.VarioSoundClass; import com.ezio.multiwii.mw.MultiWii220; import com.ezio.multiwii.mw.MultiWii230; import com.ezio.multiwii.mw.MultiWii230NAV; import com.ezio.multiwii.mw.MultirotorData; import com.ezio.multiwii.waypoints.Waypoint; import com.ezio.sec.Sec; import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GooglePlayServicesUtil; import communication.BT; import communication.BT_New; import communication.Communication; import communication.SerialCDC_ACM; import communication.SerialFTDI; public class App extends Application implements Sensors.Listener { public static final int PROTOCOL_220 = 220; public static final int PROTOCOL_230 = 230; public static final int PROTOCOL_NAV = 231; // debug public boolean D = false; // debug public String TAG = "EZGUI"; public String MapAPIKeyDebug = "0AxI9Dd4w6Y_4upkSvwAfQDK1f8fXpsnCx07vyg"; public String MapAPIKeyPublic = "0AxI9Dd4w6Y-ERQuGVB0WKB4x4iZe3uD9HVpWYQ"; // end debug///////////////// private static String REFRESHRATE = "REFRESHRATE"; public int RefreshRate = 100; // this means wait 100ms after everything is // done public Communication commMW; public Communication commFrsky; public MultirotorData mw; public Sensors sensors; public boolean FollowMeEnable = false; public boolean FollowMeBlinkFlag = false; public boolean FollowHeading = false; public boolean FollowHeadingBlinkFlag = false; public FrskyProtocol frskyProtocol; private SharedPreferences prefs; private Editor editor; public TTS tts; public SoundManager soundManager; public VarioSoundClass varioSoundClass; // variables used in FrequentJobs private boolean[] oldActiveModes; private long timer1 = 0; // Say battery level every xx seconds; // PeriodicSpeaking is the frequency in ms private long timer2 = 0; int timer2Freq = 8000;// bip when low battery private long timer3 = 0; int timer3Freq = 1000; // timer every 1sek private long timer4 = 0; int timer4Freq = 5000; // timer every 5sek public boolean loggingON = false; // ----settings----- private static final String COPYFRSKYTOMW = "COPYFRSKYTOMW"; public boolean CopyFrskyToMW; private static final String COMMUNICATION_TYPE_MW = "CommunicationTypeMW2"; public static final int COMMUNICATION_TYPE_BT = 0; public static final int COMMUNICATION_TYPE_SERIAL_FTDI = 1; public static final int COMMUNICATION_TYPE_SERIAL_OTHERCHIPS = 2; public static final int COMMUNICATION_TYPE_BT_NEW = 4; public int CommunicationTypeMW = COMMUNICATION_TYPE_BT; public static final String SERIAL_PORT_BAUD_RATE_MW = "SerialPortBaudRateMW1"; public int SerialPortBaudRateMW = 115200; public static final String SERIAL_PORT_BAUD_RATE_FRSKY = "SerialPortBaudRateFrSky1"; public int SerialPortBaudRateFrSky = 9600; private static final String COMMUNICATION_TYPE_FRSKY = "CommunicationTypeFrSky2"; public int CommunicationTypeFrSky = COMMUNICATION_TYPE_BT; private static final String RADIOMODE = "RadioMode"; public int RadioMode; private static final String PROTOCOL = "PROTOCOL4"; public int Protocol; private static final String MAGMODE = "MAGMODE"; public int MagMode; private static final String TEXTTOSPEACH = "TEXTTOSPEACH1"; public boolean TextToSpeach = true; private static final String MACADDERSS = "MACADDERSS"; public String MacAddress = ""; private static final String MACADDERSSFRSKY = "MACADDERSSFRSKY"; public String MacAddressFrsky = ""; private static final String CONNECTONSTART = "CONNECTONSTART"; public boolean ConnectOnStart = false; // private static final String ADVANCEDFUNCTIONS = "ADVANCEDFUNCTIONS"; public boolean AdvancedFunctions = false; private static final String DISABLEBTONEXIT = "DISABLEBTONEXIT"; public boolean DisableBTonExit = true; private static final String FORCELANGUAGE = "FORCELANGUAGE"; public String ForceLanguage = ""; private static final String PERIODICSPEAKING = "PERIODICSPEAKING"; public int PeriodicSpeaking = 20000; // in ms private static final String VOLTAGEALARM = "VOLTAGEALARM"; public float VoltageAlarm = 0; // private static final String USEOFFLINEMAPS = "USEOFFLINEMAPS"; // public boolean UseOfflineMaps = false; private static final String APPSTARTCOUNTER = "APPSTARTCOUNTER"; public int AppStartCounter = 0; private static final String DONATEBUTTONPRESSED = "DONATEBUTTONPRESSED"; public int DonateButtonPressed = 0; private static final String REVERSEROLL = "REVERSEROLL"; public boolean ReverseRoll = false; private static final String MAPZOOMLEVEL = "MAPZOOMLEVEL1"; public float MapZoomLevel = 9; private static final String MAPCENTERPERIOD = "MAPCENTERPERIOD"; public int MapCenterPeriod = 3; // private static final String MAINREQUESTMETHOD = "MAINREQUESTMETHOD1"; public int MainRequestMethod = 2; private static final String FRSKY_SUPPORT = "FRSKY_SUPPORT"; public boolean FrskySupport = false; private static final String NO_DATA_RECEIVED_WARNING = "NO_DATA_RECEIVED_WARNING"; public boolean NoDataReceievedWarning = true; public boolean VarioSound = false; // graphs public final String ACCROLL = "ACC ROLL"; public final String ACCPITCH = "ACC PITCH"; public final String ACCZ = "ACC Z"; public final String GYROROLL = "GYRO ROLL"; public final String GYROPITCH = "GYRO PITCH"; public final String GYROYAW = "GYRO YAW"; public final String MAGROLL = "MAG ROLL"; public final String MAGPITCH = "MAG PITCH"; public final String MAGYAW = "MAG YAW"; public final String ALT = "ALT"; public final String HEAD = "HEAD"; public final String DEBUG1 = "DEBUG1"; public final String DEBUG2 = "DEBUG2"; public final String DEBUG3 = "DEBUG3"; public final String DEBUG4 = "DEBUG4"; private final static String GRAPHSTOSHOW = "GRAPHSTOSHOW"; public String GraphsToShow = ACCROLL + ";" + ACCZ + ";" + ALT + ";" + GYROPITCH; // graphs end public Notifications notifications; private int tempLastI2CErrorCount = 0; public boolean ConfigHasBeenChange_DisplayRestartInfo = false; @Override public void onCreate() { Log.d("aaa", "APP ON CREATE"); super.onCreate(); prefs = PreferenceManager.getDefaultSharedPreferences(this); editor = prefs.edit(); Init(); tts = new TTS(getApplicationContext()); prepareSounds(); Say(getString(R.string.Started)); soundManager.playSound(2); notifications = new Notifications(getApplicationContext()); sensors = new Sensors(getApplicationContext()); sensors.registerListener(this); sensors.start(); varioSoundClass = new VarioSoundClass(); } public void Init() { ReadSettings(); ForceLanguage(); if (CommunicationTypeMW == COMMUNICATION_TYPE_BT) { commMW = new BT(getApplicationContext()); CommunicationTypeFrSky = COMMUNICATION_TYPE_BT; } if (CommunicationTypeMW == COMMUNICATION_TYPE_BT_NEW) { commMW = new BT_New(getApplicationContext()); CommunicationTypeFrSky = COMMUNICATION_TYPE_BT_NEW; } if (CommunicationTypeMW == COMMUNICATION_TYPE_SERIAL_FTDI) { commMW = new SerialFTDI(getApplicationContext()); } if (CommunicationTypeMW == COMMUNICATION_TYPE_SERIAL_OTHERCHIPS) { commMW = new SerialCDC_ACM(getApplicationContext()); } // //////////// if (CommunicationTypeFrSky == COMMUNICATION_TYPE_BT) { commFrsky = new BT(getApplicationContext()); } if (CommunicationTypeFrSky == COMMUNICATION_TYPE_BT_NEW) { commFrsky = new BT_New(getApplicationContext()); } // if (CommunicationTypeFrSky == COMMUNICATION_TYPE_SERIAL_FTDI) { // commFrsky = new SerialFTDI(getApplicationContext()); // } // // if (CommunicationTypeFrSky == COMMUNICATION_TYPE_SERIAL_OTHERCHIPS) { // commFrsky = new SerialCDC_ACM(getApplicationContext()); // } SelectProtocol(); } public void SelectProtocol() { if (Protocol == PROTOCOL_220) { mw = new MultiWii220(commMW); } if (Protocol == PROTOCOL_230) { mw = new MultiWii230(commMW); } if (Protocol == PROTOCOL_NAV) { mw = new MultiWii230NAV(commMW); } frskyProtocol = new FrskyProtocol(commFrsky); oldActiveModes = new boolean[20];// not the best method } public void ReadSettings() { RadioMode = prefs.getInt(RADIOMODE, 2); Protocol = prefs.getInt(PROTOCOL, 220); MagMode = prefs.getInt(MAGMODE, 1); TextToSpeach = prefs.getBoolean(TEXTTOSPEACH, true); MacAddress = prefs.getString(MACADDERSS, ""); MacAddressFrsky = prefs.getString(MACADDERSSFRSKY, ""); ConnectOnStart = prefs.getBoolean(CONNECTONSTART, false); // AdvancedFunctions = prefs.getBoolean(ADVANCEDFINCTIONS, false); AdvancedFunctions = (Sec.VerifyDeveloperID(Sec.GetDeviceID(getApplicationContext()), Sec.TestersIDs)); if (AdvancedFunctions) Toast.makeText(getApplicationContext(), "You are a tester", Toast.LENGTH_SHORT).show(); DisableBTonExit = prefs.getBoolean(DISABLEBTONEXIT, true); ForceLanguage = prefs.getString(FORCELANGUAGE, ""); PeriodicSpeaking = prefs.getInt(PERIODICSPEAKING, 20000); VoltageAlarm = prefs.getFloat(VOLTAGEALARM, 9.9f); GraphsToShow = prefs.getString(GRAPHSTOSHOW, GraphsToShow); // UseOfflineMaps = prefs.getBoolean(USEOFFLINEMAPS, false); RefreshRate = prefs.getInt(REFRESHRATE, 100); CopyFrskyToMW = prefs.getBoolean(COPYFRSKYTOMW, false); AppStartCounter = prefs.getInt(APPSTARTCOUNTER, 0); DonateButtonPressed = prefs.getInt(DONATEBUTTONPRESSED, 0); ReverseRoll = prefs.getBoolean(REVERSEROLL, false); MapZoomLevel = prefs.getFloat(MAPZOOMLEVEL, 9); MapCenterPeriod = prefs.getInt(MAPCENTERPERIOD, 3); CommunicationTypeMW = prefs.getInt(COMMUNICATION_TYPE_MW, COMMUNICATION_TYPE_BT); // CommunicationTypeFrSky = prefs.getInt(COMMUNICATION_TYPE_FRSKY, // COMMUNICATION_TYPE_BT); SerialPortBaudRateMW = prefs.getInt(SERIAL_PORT_BAUD_RATE_MW, 115200); SerialPortBaudRateFrSky = prefs.getInt(SERIAL_PORT_BAUD_RATE_FRSKY, 9600); // MainRequestMethod = prefs.getInt(MAINREQUESTMETHOD, 2); FrskySupport = prefs.getBoolean(FRSKY_SUPPORT, false); NoDataReceievedWarning = prefs.getBoolean(NO_DATA_RECEIVED_WARNING, true); } public void SaveSettings(boolean quiet) { editor.putInt(RADIOMODE, RadioMode); editor.putInt(PROTOCOL, Protocol); editor.putInt(MAGMODE, MagMode); editor.putBoolean(TEXTTOSPEACH, TextToSpeach); editor.putString(MACADDERSS, MacAddress); editor.putString(MACADDERSSFRSKY, MacAddressFrsky); editor.putBoolean(CONNECTONSTART, ConnectOnStart); editor.putBoolean(DISABLEBTONEXIT, DisableBTonExit); editor.putString(FORCELANGUAGE, ForceLanguage); editor.putInt(PERIODICSPEAKING, PeriodicSpeaking); editor.putFloat(VOLTAGEALARM, VoltageAlarm); editor.putString(GRAPHSTOSHOW, GraphsToShow); editor.putInt(REFRESHRATE, RefreshRate); editor.putBoolean(COPYFRSKYTOMW, CopyFrskyToMW); editor.putInt(APPSTARTCOUNTER, AppStartCounter); editor.putInt(DONATEBUTTONPRESSED, DonateButtonPressed); editor.putBoolean(REVERSEROLL, ReverseRoll); editor.putFloat(MAPZOOMLEVEL, MapZoomLevel); editor.putInt(MAPCENTERPERIOD, MapCenterPeriod); editor.putInt(COMMUNICATION_TYPE_MW, CommunicationTypeMW); editor.putInt(SERIAL_PORT_BAUD_RATE_MW, SerialPortBaudRateMW); editor.putBoolean(FRSKY_SUPPORT, FrskySupport); editor.putBoolean(NO_DATA_RECEIVED_WARNING, NoDataReceievedWarning); editor.commit(); if (!quiet) { Toast.makeText(getApplicationContext(), getString(R.string.Settingssaved), Toast.LENGTH_LONG).show(); // Say(getString(R.string.Settingssaved)); } } @Override public void onTerminate() { sensors.stop(); mw.CloseLoggingFile(); super.onTerminate(); } public void Say(String text) { if (TextToSpeach) tts.Speak(text); } public void Frequentjobs() { // rssi if (!commFrsky.Connected && commMW.Connected) { frskyProtocol.TxRSSI = Functions.map(mw.rssi, 0, 1024, 0, 110); } // Copy data from FrSky if (CopyFrskyToMW && commFrsky.Connected && !commMW.Connected) FrskyToMW(); // Say battery level every xx seconds if (PeriodicSpeaking > 0 && (commMW.Connected || commFrsky.Connected) && timer1 < System.currentTimeMillis()) { timer1 = System.currentTimeMillis() + PeriodicSpeaking; if (mw.bytevbat > 10) { Say(getString(R.string.BatteryLevelIs) + " " + String.valueOf((float) (mw.bytevbat / 10f)) + " " + getString(R.string.TTS_Volts)); } if (mw.alt != 0) { Say(getString(R.string.TTS_Altitude) + " " + String.valueOf((int) mw.alt) + " " + getString(R.string.TTS_Meters)); } } // beep when low battery if (mw.bytevbat > 10 && VoltageAlarm > 0 && (commMW.Connected || commFrsky.Connected) && timer2 < System.currentTimeMillis() && (float) (mw.bytevbat / 10f) < VoltageAlarm) { timer2 = System.currentTimeMillis() + timer2Freq; soundManager.playSound(0); } // ===================timer every 1sek=============================== if (timer3 < System.currentTimeMillis()) { timer3 = System.currentTimeMillis() + timer3Freq; // Notifications if (mw.i2cError != tempLastI2CErrorCount) { notifications.displayNotification(getString(R.string.Warning), "I2C Error=" + String.valueOf(mw.i2cError), true, 1, false); tempLastI2CErrorCount = mw.i2cError; } if (mw.DataFlow < 0 && NoDataReceievedWarning) { notifications.displayNotification(getString(R.string.Warning), getString(R.string.NoDataRecieved) + " " + String.valueOf(mw.DataFlow), true, 1, false); } // Checkboxes speaking; ON OFF for (int i = 0; i < mw.CHECKBOXITEMS; i++) { if (mw.ActiveModes[i] != oldActiveModes[i]) { String s = ""; if (mw.ActiveModes[i]) { s = getString(R.string.isON); soundManager.playSound(2); } else { s = getString(R.string.isOFF); } Say((mw.BoxNames[i] + s).toLowerCase(Locale.ENGLISH)); if (mw.BoxNames[i].equals("ARM")) { soundManager.playSound(1); mw.ZeroConnection(); } } oldActiveModes[i] = mw.ActiveModes[i]; } // followHeading if (FollowHeading) { mw.SendRequestMSP_SET_HEAD((int) sensors.Heading); FollowHeadingBlinkFlag = !FollowHeadingBlinkFlag; } if (VarioSound) { varioSoundClass.Play(1000 + mw.vario * 20); } } // --------------------END timer every 1sek--------------------------- // ===================timer every 5sek=============================== if (timer4 < System.currentTimeMillis()) { timer4 = System.currentTimeMillis() + timer4Freq; // // Reconecting // if (commMW.ConnectionLost) { // if (commMW.ReconnectTry < 1) { // tts.Speak(getString(R.string.Reconnecting)); // commMW.Connect(MacAddress, SerialPortBaudRateMW); // commMW.ReconnectTry++; // } // } // update Home position if (commMW.Connected && Protocol < 231) { mw.SendRequestMSP_WP(0); for (int i = 0; i < mw.CHECKBOXITEMS; i++) { if (mw.BoxNames[i].equals("GPS HOLD")) { if (mw.ActiveModes[i]) { // update Position hold mw.SendRequestMSP_WP(16); } else { mw.Waypoints[16].Lat = 0; mw.Waypoints[16].Lon = 0; } } } } String t = new String(); if (mw.version > 0) { if (mw.version > Protocol) { t += getString(R.string.SelectDifferentProtocol); } } if (mw.multi_Capability.Nav && Protocol != PROTOCOL_NAV) { Protocol = PROTOCOL_NAV; SaveSettings(true); RestartApp(); } if (sensors.MockLocationWorking) t += getString(R.string.MockLocationIsWorking) + ";"; if (FollowMeEnable) t += getString(R.string.Follow_Me) + ";"; if (FollowHeading) t += "Follow Heading"; notifications.displayNotification("Status", t, false, 99, false); } // --------------------END timer every 5sek--------------------------- } private void prepareSounds() { soundManager = new SoundManager(getApplicationContext()); soundManager.addSound(0, R.raw.alarma); soundManager.addSound(1, R.raw.alert1); soundManager.addSound(2, R.raw.blip); } public void ForceLanguage() { if (!ForceLanguage.equals("")) { String languageToLoad = ForceLanguage; Locale locale = new Locale(languageToLoad); Locale.setDefault(locale); Configuration config = new Configuration(); config.locale = locale; getBaseContext().getResources().updateConfiguration(config, null); } } // public void ConnectionBug() { // autoconnect again when new activity is // // started // if (ConnectOnStart && !commMW.Connected) { // commMW.Connect(MacAddress, SerialPortBaudRateMW); // Say(getString(R.string.menu_connect)); // } // } private void FrskyToMW() { mw.angx = frskyProtocol.frskyHubProtocol.angX; mw.angy = frskyProtocol.frskyHubProtocol.angY; mw.ax = frskyProtocol.frskyHubProtocol.Acc_X; mw.ay = frskyProtocol.frskyHubProtocol.Acc_Y; mw.az = frskyProtocol.frskyHubProtocol.Acc_Z; mw.head = frskyProtocol.frskyHubProtocol.Heading; mw.GPS_numSat = frskyProtocol.frskyHubProtocol.Temperature_1; mw.GPS_speed = frskyProtocol.frskyHubProtocol.GPS_Speed; mw.GPS_latitude = (int) frskyProtocol.frskyHubProtocol.GPS_Latitude; mw.GPS_longitude = (int) frskyProtocol.frskyHubProtocol.GPS_Longtitude; mw.alt = frskyProtocol.frskyHubProtocol.Altitude; mw.bytevbat = (byte) frskyProtocol.frskyHubProtocol.Voltage; } @Override public void onSensorsStateChangeMagAcc() { } @Override public void onSensorsStateGPSLocationChange() { if (FollowMeEnable) { // TODO needs more work here mw.SendRequestMSP_SET_WP(new Waypoint(0, (int) (sensors.MapCurrentPosition.latitude * 1e7), (int) (sensors.MapCurrentPosition.longitude * 1e7), 0, 0, 0, 0)); mw.SendRequestMSP_SET_WP(new Waypoint(16, (int) (sensors.MapCurrentPosition.latitude * 1e7), (int) (sensors.MapCurrentPosition.longitude * 1e7), 0, 0, 0, 0)); FollowMeBlinkFlag = !FollowMeBlinkFlag; } } @Override public void onSensorsStateGPSStatusChange() { } public void OpenInfoOnClick(View v) { { Log.d("aaa", "OpenInfoOnClick " + v.getTag().toString()); final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse(v.getTag().toString())); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); } } public boolean checkGooglePlayServicesAvailability(Activity activity) { int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(activity); if (resultCode != ConnectionResult.SUCCESS) { Dialog dialog = GooglePlayServicesUtil.getErrorDialog(resultCode, activity, 69); if (dialog != null) { dialog.show(); return false; } else { showOkDialogWithText(activity, "Something went wrong. Please make sure that you have the Play Store installed and that you are connected to the internet."); return false; } } Log.d("GooglePlayServicesUtil Check", "Result is: " + resultCode); return true; } private void showOkDialogWithText(Context context, String messageText) { Builder builder = new AlertDialog.Builder(context); builder.setMessage(messageText); builder.setCancelable(true); builder.setPositiveButton("OK", null); AlertDialog dialog = builder.create(); dialog.show(); } public void RestartApp() { Intent mStartActivity = new Intent(getApplicationContext(), MainMultiWiiActivity.class); int mPendingIntentId = 123456; PendingIntent mPendingIntent = PendingIntent.getActivity(getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT); AlarmManager mgr = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 200, mPendingIntent); System.exit(0); } }