StevenMHernandez / Android-CSI-Labelling-App

Android App for labelling CSI collected through the [ESP32 CSI Toolkit](https://stevenmhernandez.github.io/ESP32-CSI-Tool/)
27 stars 7 forks source link

Create a new Activity to visualize CSI data #6

Open StevenMHernandez opened 2 years ago

StevenMHernandez commented 2 years ago

In an older version of this project, I had a way to visualize CSI live. See: (https://github.com/StevenMHernandez/Android-CSI-Labelling-App/issues/5#issuecomment-1081972957) The (private) implementation can be found here: (https://github.com/StevenMHernandez/AndroidCSICollector/blob/master/app/src/main/java/com/stevenmhernandez/csicollector/MainActivity.java)

gmcd310 commented 2 years ago

Dear Steven,This link won't open。 image

StevenMHernandez commented 2 years ago

Yes, it is a private codebase currently.

gmcd310 commented 2 years ago

How do I view the code

StevenMHernandez commented 2 years ago

Sorry, the link was for my own future reference.

Are you are interested in helping contributing to this open source codebase? If so, below is the untested and slightly edited code that I was linking. Try to create a new Activity (VisualizationMainActivity.java). You can use this code as a starting point, however, you will need to fix any issues that you find yourself. It might be useful to also use https://github.com/StevenMHernandez/Android-CSI-Labelling-App/blob/master/app/src/main/java/com/stevenmhernandez/csi_labelling_app/Experiments/ToggleMainActivity.java as a reference too.

public class VisualizationMainActivity extends AppCompatActivity implements CSIDataInterface {

    public static final String TAG = "VisualizationMainActivity";

    public ImageView imageView;
    public Button toggleHeatmapButton;
    public Button toggleFrameRateButton;
    public TextView experimentTextView;
    public TextView frameRateTextView;
    public TextView totalFrameRateTextView;

    Bitmap bmCurrent;

    double heatmapMax = 0;
    double heatmapMin = 9999;

    BaseDataCollectorService dataCollectorService = new FileDataCollectorService();

    final Handler handler = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        dataCollectorService.setup(this);

        this.imageView = findViewById(R.id.imageView);
        this.toggleHeatmapButton = findViewById(R.id.toggleHeatmapButton);
        this.toggleFrameRateButton = findViewById(R.id.toggleFrameRateButton);
        this.experimentTextView = findViewById(R.id.experimentTextView);
        this.frameRateTextView = findViewById(R.id.frameRateTextView);
        this.totalFrameRateTextView = findViewById(R.id.totalFrameRateTextView);
    }

    private double[] parseCsi(String csi, boolean returnPhases) {
        String[] strs = csi.trim().split(" ");
        try {
            int[] im_ints = new int[strs.length / 2];
            int[] real_ints = new int[strs.length / 2];
            double[] amplitudes = new double[strs.length / 2];
            double[] phases = new double[strs.length / 2];

            for (int i = 0; i < strs.length; i++) {
                if (i % 2 == 0) {
                    im_ints[(int) Math.floor(i / 2.0)] = Integer.parseInt(strs[i]);
                } else {
                    real_ints[(int) Math.floor(i / 2.0)] = Integer.parseInt(strs[i]);
                }
            }

            for (int i = 0; i < strs.length / 2; i++) {
                amplitudes[i] = Math.sqrt(im_ints[i] ^ 2 + real_ints[i] ^ 2);
                phases[i] = Math.atan2(im_ints[i], real_ints[i]);
            }

            if (returnPhases) {
                return phases;
            } else {
                return amplitudes;
            }
        } catch (Exception e) {
            Log.e("Some error in parsing CSI String", csi);
            Log.e("ERROR:", e.getLocalizedMessage());
        }

        return null;
    }

    long sampleRateStartTime = 0;
    int sampleCount = 0;
    int totalSampleCount = 0;
    boolean CONFIG_PRINT_SAMPLE_RATE = true;
    boolean CONFIG_PRINT_HEATMAP = false;

    private void addCsi(String csi) {
        if (CONFIG_PRINT_SAMPLE_RATE) {
            if (sampleRateStartTime + 1000 < System.currentTimeMillis()) {
                this.frameRateTextView.setText(Integer.toString(sampleCount) + " samples last second");
                sampleRateStartTime = System.currentTimeMillis();
                sampleCount = 0;
            }

            sampleCount++;
            totalSampleCount++;

            this.totalFrameRateTextView.setText(Integer.toString(totalSampleCount) + " samples collected");
        }
        if (CONFIG_PRINT_HEATMAP) {
            if (bmCurrent == null) {
                bmCurrent = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
                bmCurrent = Bitmap.createScaledBitmap(bmCurrent, 64, 100, false);
            }

            double[] amplitudes = parseCsi(csi, false);

            if (amplitudes != null) {
                Bitmap bm = bmCurrent;

                int width = bm.getWidth();
                int height = bm.getHeight();

                Log.i("width", String.valueOf(width));
                Log.i("height", String.valueOf(height));

                int[] pixels = new int[(width + 2) * (height + 2)];
                bm.getPixels(pixels, height, width, 0, 1, width, height - 1);
                bm.setPixels(pixels, height, width, 0, 0, width, height - 1);
                for (int i = 0; i < Math.min(amplitudes.length, 64); i++) {
                    if (amplitudes[i] > heatmapMax) {
                        heatmapMax = amplitudes[i];
                    }
                    if (amplitudes[i] < heatmapMin) {
                        heatmapMin = amplitudes[i];
                    }
                    bm.setPixel(i, height - 1, Color.rgb((int) ((amplitudes[i] - heatmapMin) * (heatmapMax - heatmapMin) * 256.0), 0, 0));
                }

                bmCurrent = bm;

                Bitmap finalBm = Bitmap.createScaledBitmap(bmCurrent, 640, 1000, false);

                this.imageView.setImageBitmap(finalBm);
            }
        }
    }

    public void toggleHeatmap(View view) {
        CONFIG_PRINT_HEATMAP = !CONFIG_PRINT_HEATMAP;
        toggleHeatmapButton.setText(CONFIG_PRINT_HEATMAP ? "HM OFF" : "HM ON");
    }

    public void toggleFrameRate(View view) {
        CONFIG_PRINT_SAMPLE_RATE = !CONFIG_PRINT_SAMPLE_RATE;
        if (CONFIG_PRINT_SAMPLE_RATE) {
            toggleFrameRateButton.setText("FR OFF");
        } else {
            toggleFrameRateButton.setText("FR ON");
            frameRateTextView.setText("");
            totalFrameRateTextView.setText("");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        csiSerial.onResume(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        csiSerial.onPause(this);
    }

    public String updateCsiString(Activity activity, String currentAction) {
        String deviceId = Settings.Secure.getString(activity.getContentResolver(), Settings.Secure.ANDROID_ID);
        return String.format("CURRENT_ACTION,%s,%d,%s\n", deviceId, System.currentTimeMillis(), currentAction);
    }

    long csiCounter = 0;
    long csiPerSecondCounter = 0;
    long counterStart = System.currentTimeMillis();
    long csiPerSecondCounterFinal = 0;
}

Currently, I am too busy to work on this myself.

gmcd310 commented 2 years ago

Thank you very much,I will to try