/** @file TimerTask.java * * @author marco corvi * @date jan 2014 * * @brief TopoDroid timer * -------------------------------------------------------- * Copyright This sowftare is distributed under GPL-3.0 or later * See the file COPYING. * -------------------------------------------------------- */ package com.topodroid.DistoX; import android.content.Context; import android.os.AsyncTask; import android.media.AudioManager; import android.media.ToneGenerator; import android.hardware.SensorManager; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; public class TimerTask extends AsyncTask<String, Integer, Long > implements SensorEventListener { int mCntAcc; int mCntMag; float mValAcc[] = new float[3]; float mValMag[] = new float[3]; Context mContext; IBearingAndClino mParent; boolean mRun; TimerTask( Context context, IBearingAndClino parent ) { mContext = context; mParent = parent; mRun = true; } @Override protected Long doInBackground( String... str ) { int count = TDSetting.mTimerCount; int duration = 100; // ms ToneGenerator toneG = new ToneGenerator( AudioManager.STREAM_ALARM, TDSetting.mBeepVolume ); long ret = 0; mCntAcc = 0; mCntMag = 0; for ( int i=0; i<count && mRun; ++i ) { toneG.startTone( ToneGenerator.TONE_PROP_BEEP, duration ); try { Thread.sleep( 1000 - duration ); } catch ( InterruptedException e ) { } if ( isCancelled() ) { mRun = false; break; } } if ( mRun ) { int cnt = 0; mValAcc[0] = 0; mValAcc[1] = 0; mValAcc[2] = 0; mValMag[0] = 0; mValMag[1] = 0; mValMag[2] = 0; SensorManager sensor_manager = (SensorManager)mContext.getSystemService( Context.SENSOR_SERVICE ); Sensor mAcc = sensor_manager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER ); Sensor mMag = sensor_manager.getDefaultSensor( Sensor.TYPE_MAGNETIC_FIELD ); if ( mAcc != null && mMag != null ) { sensor_manager.registerListener( this, mAcc, SensorManager.SENSOR_DELAY_NORMAL ); sensor_manager.registerListener( this, mMag, SensorManager.SENSOR_DELAY_NORMAL ); while ( cnt < 100 && ( mCntAcc < 10 || mCntMag < 10 ) ) { toneG.startTone( ToneGenerator.TONE_PROP_BEEP, duration ); try{ ++ cnt; Thread.sleep( 100 ); } catch ( InterruptedException e ) { } } sensor_manager.unregisterListener( this ); } } return ret; } @Override protected void onProgressUpdate(Integer... progress) { } @Override protected void onPostExecute(Long result) { if ( mCntAcc > 0 && mCntMag > 0 && mRun ) { mValAcc[0] /= mCntAcc; mValAcc[1] /= mCntAcc; mValAcc[2] /= mCntAcc; mValMag[0] /= mCntMag; mValMag[1] /= mCntMag; mValMag[2] /= mCntMag; computeBearingAndClino(); } } @Override public void onAccuracyChanged( Sensor sensor, int accuracy ) { } @Override public void onSensorChanged( SensorEvent event ) { float[] value = event.values; switch ( event.sensor.getType() ) { case Sensor.TYPE_MAGNETIC_FIELD: ++ mCntMag; mValMag[0] += value[0]; mValMag[1] += value[1]; mValMag[2] += value[2]; break; case Sensor.TYPE_ACCELEROMETER: ++ mCntAcc; mValAcc[0] += value[0]; mValAcc[1] += value[1]; mValAcc[2] += value[2]; break; } } private void computeBearingAndClino( ) { Vector g = new Vector( mValAcc[0], mValAcc[1], mValAcc[2] ); Vector m = new Vector( mValMag[0], mValMag[1], mValMag[2] ); g.normalize(); m.normalize(); // Vector e = new Vector( 1.0f, 0.0f, 0.0f ); Vector w = m.cross( g ); // west Vector n = g.cross( w ); // north w.normalize(); n.normalize(); float b0 = TDMath.atan2( -w.y, n.y ); float c0 = - TDMath.atan2( g.y, TDMath.sqrt(w.y*w.y+n.y*n.y) ); if ( b0 < 0.0f ) b0 += TDMath.M_2PI; // if ( r0 < 0.0f ) r0 += TDMath.M_2PI; b0 = 360 - b0 * 360.0f / TDMath.M_2PI; c0 = 0 - c0 * 360.0f / TDMath.M_2PI; mParent.setBearingAndClino( b0, c0 ); } }