package org.droidplanner.android.fragments; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageButton; import android.widget.PopupWindow; import android.widget.TextView; import com.o3dr.android.client.Drone; import com.o3dr.services.android.lib.drone.attribute.AttributeEvent; import com.o3dr.services.android.lib.drone.attribute.AttributeType; import com.o3dr.services.android.lib.drone.property.Altitude; import com.o3dr.services.android.lib.drone.property.Attitude; import com.o3dr.services.android.lib.drone.property.Speed; import org.beyene.sius.unit.length.LengthUnit; import org.droidplanner.android.R; import org.droidplanner.android.fragments.helpers.ApiListenerFragment; import org.droidplanner.android.utils.unit.providers.speed.SpeedUnitProvider; import org.droidplanner.android.widgets.AttitudeIndicator; public class TelemetryFragment extends ApiListenerFragment { private final static IntentFilter eventFilter = new IntentFilter(); static { eventFilter.addAction(AttributeEvent.ATTITUDE_UPDATED); eventFilter.addAction(AttributeEvent.SPEED_UPDATED); eventFilter.addAction(AttributeEvent.STATE_UPDATED); } /** * This is the period for the flight time update. */ protected final static long FLIGHT_TIMER_PERIOD = 1000l; // 1 second private final BroadcastReceiver eventReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); final Drone drone = getDrone(); switch (action) { case AttributeEvent.ATTITUDE_UPDATED: final Attitude attitude = drone.getAttribute(AttributeType.ATTITUDE); onOrientationUpdate(attitude); break; case AttributeEvent.SPEED_UPDATED: final Speed droneSpeed = drone.getAttribute(AttributeType.SPEED); onSpeedUpdate(droneSpeed); final Altitude droneAltitude = drone.getAttribute(AttributeType.ALTITUDE); onAltitudeUpdate(droneAltitude); break; case AttributeEvent.STATE_UPDATED: updateFlightTimer(); break; } } }; /** * Runnable used to update the drone flight time. */ protected Runnable mFlightTimeUpdater = new Runnable() { @Override public void run() { mHandler.removeCallbacks(this); final Drone drone = getDrone(); if (drone == null || !drone.isConnected()) return; if (flightTimer != null) { long timeInSeconds = drone.getFlightTime(); long minutes = timeInSeconds / 60; long seconds = timeInSeconds % 60; flightTimer.setText(String.format("%02d:%02d", minutes, seconds)); } mHandler.postDelayed(this, FLIGHT_TIMER_PERIOD); } }; /** * This handler is used to update the flight time value. */ protected final Handler mHandler = new Handler(); private AttitudeIndicator attitudeIndicator; private TextView roll; private TextView yaw; private TextView pitch; private TextView groundSpeed; private TextView airSpeed; private TextView climbRate; private TextView altitude; private TextView flightTimer; private boolean headingModeFPV; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_telemetry, container, false); attitudeIndicator = (AttitudeIndicator) view.findViewById(R.id.aiView); roll = (TextView) view.findViewById(R.id.rollValueText); yaw = (TextView) view.findViewById(R.id.yawValueText); pitch = (TextView) view.findViewById(R.id.pitchValueText); groundSpeed = (TextView) view.findViewById(R.id.groundSpeedValue); airSpeed = (TextView) view.findViewById(R.id.airSpeedValue); climbRate = (TextView) view.findViewById(R.id.climbRateValue); altitude = (TextView) view.findViewById(R.id.altitudeValue); flightTimer = (TextView) view.findViewById(R.id.flight_timer); final Resources res = getResources(); final int popupWidth = ViewGroup.LayoutParams.WRAP_CONTENT; final int popupHeight = ViewGroup.LayoutParams.WRAP_CONTENT; final Drawable popupBg = res.getDrawable(android.R.color.transparent); final View resetTimerView = inflater.inflate(R.layout.popup_info_flight_time, container, false); final PopupWindow resetTimerPopup = new PopupWindow(resetTimerView, popupWidth, popupHeight, true); resetTimerPopup.setBackgroundDrawable(popupBg); final TextView resetTimer = (TextView) resetTimerView.findViewById(R.id.bar_flight_time_reset_timer); resetTimer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { final Drone drone = getDrone(); if(drone != null && drone.isConnected()) drone.resetFlightTimer(); updateFlightTimer(); resetTimerPopup.dismiss(); } }); final ImageButton resetFlightTimerButton = (ImageButton) view.findViewById(R.id.reset_flight_timer_button); resetFlightTimerButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resetTimerPopup.showAsDropDown(resetFlightTimerButton); } }); return view; } @Override public void onStart() { super.onStart(); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); headingModeFPV = prefs.getBoolean("pref_heading_mode", false); } private void updateFlightTimer(){ final Drone drone = getDrone(); mHandler.removeCallbacks(mFlightTimeUpdater); if (drone != null && drone.isConnected()) { mFlightTimeUpdater.run(); } else { flightTimer.setText("00:00"); } } @Override public void onApiConnected() { updateFlightTimer(); getBroadcastManager().registerReceiver(eventReceiver, eventFilter); } @Override public void onApiDisconnected() { getBroadcastManager().unregisterReceiver(eventReceiver); } public void onOrientationUpdate(Attitude droneAttitude) { if (droneAttitude == null) return; float r = (float) droneAttitude.getRoll(); float p = (float) droneAttitude.getPitch(); float y = (float) droneAttitude.getYaw(); if (!headingModeFPV & y < 0) { y = 360 + y; } attitudeIndicator.setAttitude(r, p, y); roll.setText(String.format("%3.0f\u00B0", r)); pitch.setText(String.format("%3.0f\u00B0", p)); yaw.setText(String.format("%3.0f\u00B0", y)); } private void onSpeedUpdate(Speed speed) { if (speed != null) { final SpeedUnitProvider speedUnitProvider = getSpeedUnitProvider(); airSpeed.setText(speedUnitProvider.boxBaseValueToTarget(speed.getAirSpeed()).toString()); groundSpeed.setText(speedUnitProvider.boxBaseValueToTarget(speed.getGroundSpeed()).toString()); climbRate.setText(speedUnitProvider.boxBaseValueToTarget(speed.getVerticalSpeed()).toString()); } } private void onAltitudeUpdate(Altitude altitude) { if (altitude != null) { double alt = altitude.getAltitude(); LengthUnit altUnit = getLengthUnitProvider().boxBaseValueToTarget(alt); this.altitude.setText(altUnit.toString()); } } }