Retrofit2 Rxjava2 Error Response Handling in Open Event Organizer App

In the Open Event Organizer Android app the challenge is to provide user, a readable error description for the input requests. The Organizer App was showing a coded message which was understandable only to a programmer making it unfriendly to the common user. The blog describes how we tackled this problem and implemented a mechanism to provide user friendly error messages for user requests (if any).

Let’s consider the scenario when an organizer want to create an Event or maybe a Ticket so what he has to do is fill out a form containing some user input fields and click on submit button to send the data to the server which in turn sends a response for the request. If the information is valid the server sends a HTTP 201 Response and user gets feedback that the Event/Ticket is created. But if the information is not valid the user gets feedback that there is HTTP 422 error in your request. There is no readable description of error provided to the user.

To handle this problem we will be using Retrofit 2.3.0 to make Network Requests, which is a REST client for Android and Java by Square Inc. It makes it relatively easy to retrieve and upload JSON (or other structured data) via a REST based Web Service. Further, we will be using other awesome libraries like RxJava 2.1.10 (by ReactiveX) to handle tasks asynchronously, Jackson, Jasminb-Json-Api in an MVP architecture. Let’s move on to the code.

Retrofit to the rescue

Now we will see how we can extract the details about the error response and provide user a better feedback rather than just throwing the error code.

Firstly let’s make the Request to our REST API Server using Retrofit2.

@POST(“faqs”)
Observable<Faq> postFaq(@Body Faq faq);

Here we are making a POST request and expecting a Observable<Faq> Response from the server.The  @Body annotation indicates the Request Body is an Faq object.

Please note that Observable used here is ReactiveX Observable so don’t confuse it with java.util Observable.

public class Faq {
@Id(LongIdHandler.class)
public Long id;  @Relationship(“event”)
@ForeignKey(stubbedRelationship = true,

onDelete = ForeignKeyAction.CASCADE)
public Event event;

public String question;
public String answer;
}

Let’s say the API declares both question and answer as mandatory fields  for creation of an Faq. We supply the following input to the app.

question = “Do I need to buy a Ticket to get In ?”;
answer = null

We used RxJava to make an asynchronous request to server. In case of error we will get a Retrofit throwable and we will pass that on to ErrorUtils.java which will do all the processing and return a readable error message.

faqRepository
.createFaq(faq)
.compose(dispose(getDisposable()))
.compose(progressive(getView()))  .doOnError(throwable ->

getView().showError(ErrorUtils.getMessage(throwable)))
.subscribe(createdFaq -> {
getView().onSuccess(“Faq Created”);
getView().dismiss();
}, Logger::logError);

Now we will extract the ResponseBody from the Retrofit throwable.

ResponseBody responseBody = ((HttpException) throwable)

.response().errorBody();
return getErrorDetails(responseBody);

The ResponseBody is a JSON containing all the information about the error.

{
“errors”: [
{
“status”: “422”,
“source”: {
“pointer”: “/data/attributes/answer”
},
“detail”: “Missing data for required field.”,
“title”: “Validation error”
}
],
“jsonapi”: {
“version”: “1.0”
}
}

In order to provide better feedback to user regarding the error we have to parse the response JSON and extract the pointed field (which in this case is – “answer”) and then combine it with the value corresponding to the “detail” key. Following is the relevant section from ErrorUtils.java (for viewing the complete ErrorUtils.java please refer here).

public static String getErrorDetails(ResponseBody responseBody) {
try {
JSONObject jsonObject = new JSONObject(responseBody.string());
JSONObject jsonArray = new    JSONObject(jsonObject.getJSONArray(“errors”).get(0).toString());
JSONObject errorSource =

new JSONObject(jsonArray.get(“source”).toString());

try {
String pointedField =

getPointedField(errorSource.getString(“pointer”));
if (pointedField == null)
return jsonArray.get(“detail”).toString();
else
return jsonArray.get(“detail”).toString()

.replace(“.”, “”) + “: ” + pointedField;
} catch (Exception e) {
return jsonArray.get(“detail”).toString();
}

} catch (Exception e) {
return null;
}
}

public static String getPointedField(String pointerString) {
if (pointerString == null || Utils.isEmpty(pointerString))
return null;
else {
String[] path = pointerString.split(“/”);
if (path.length > 3)
return path[path.length – 1];
else
return null;
}
}

The final error message returned by ErrorUtils in case of HTTP 422 –

Missing data for required field: answer

Similar approach can be followed for extracting the error “title” or “status” .

References

  1. Official documentation of Retrofit 2.x http://square.github.io/retrofit/
  2. Official documentation for RxJava 2.x https://github.com/ReactiveX/RxJava
  3. Codebase for Open Event Organizer App on Github https://github.com/fossasia/open-event-orga-app
Continue ReadingRetrofit2 Rxjava2 Error Response Handling in Open Event Organizer App

Implementing Rotary Knob in PSLab Android App

PSLab android application as we all know has got various instrument such as oscilloscope, logic analyzer, wave generator, etc.. . Although many of  these instrument require redesigning of it’s UI. One such instrument is the  Multimeter. The Multimeter UI required the implementation of the rotary knob as it is also present in an actual Multimeter.Thus this blog is solely on how to implement a Rotary Knob in an Android App.

Figure 1: Showing a basic knob

What is Rotary Knob ?

A Rotary knob is  a customizable selector that replicates the behaviour of a knob with discrete values.The knob is a powerful tool it has a lot of advantages over other radio-buttons, seek bars or other selectors.[1][2]

      • It has an immediate graphical indication of the current value, the number of choices and where the value is in the overall range.
      • Works fine also with few choices, as a multi-state toggle.
      • Swipe gestures allow to change values very quickly, using the entire screen for the gesture, but only a tiny zone of it for the graphics.

Implementation of Rotary Knob in your app[1]

In this blog the rotary knob is implemented using the BeppiMenozzi Knob library[1] as by doing this we don’t have to manually create the extra class for the knob and we don’t have to write the code from scratch.

This blog will give you step by step guide on how to implement this on your app.

        1. In your project level build.gradle file add the following lines of code.
          allprojects {
            repositories {
                   ….
                maven { url "https://jitpack.io" }
                ….
            }
          }
        2. In you app level build.gradle file add the following lines of codes in your dependencies.
          compile 'com.github.BeppiMenozzi:Knob:1.9.
        3. Minimal code :-
          This contains the minimum number of lines of code for knob

          xmlns:app="http://schemas.android.com/apk/res-auto"
          ...
          <it.beppi.knoblibrary.Knob
                  android:layout_width="64dp"
                  android:layout_height="64dp"
                  android:id="@+id/knob"
                  app:kNumberOfStates="6"
           />

          Java listener-

          xmlns:app="http://schemas.android.com/apk/res-auto"
          Knob knob = (Knob) findViewById(R.id.knob);
          knob.setState(firstState);
          knob.setOnStateChanged(new Knob.OnStateChanged() {
                  @Override
                  public void onState(int state) {
                  // do something
                  }
              });

          This java method gives the user the position of the tip of theknob.
          Also there are various other advantages of using this library.

              • The Knob is completely customizable. The many customizable attributes can all be set both via xml file, and programmatically.
              • This  page gives the list of all the methods for customizing a knob.

           

        4.  Implementing a simple knob app
          tv= (TextView)findViewById(R.id.tv);
          Knob knob = (Knob) findViewById(R.id.knob);
          knob.setState(0);
          knob.setOnStateChanged(new Knob.OnStateChanged() {
             @Override
             public void onState(int state) {
                 // do something
                 tv.setText(String.valueOf(state));
             }
          });

Now let us see the implementation of this simple app

Figure 2: showing basic knob implementation in android

So this is how we can implement a rotary knob in any Android Application.

Resources:

 

 

 

Continue ReadingImplementing Rotary Knob in PSLab Android App

Producing Waveforms using Wave Generator module in the PSLab Android App

This blog will demonstrate how to produce different waveforms using the Wave Generator module in the PSLab android app and view them on the Oscilloscope.

The Wave Generator in PSLab android app is simple to use and has a UI which is similar to physical commodity wave generators. It is capable of producing different waveforms like sine, sawtooth and square wave.

Apparatus Required

Before getting started with the wave generator we require the following items:

  1. PSLab device
  2. An android phone with PSLab app installed in it.
  3. USB cable (Mini B)
  4. OTG(On the Go) wire
  5. Some connecting wires having pins at both ends

Understanding the Wave Generator Pins

Figure 1 shows the pin diagram of the PSLab device

Let me briefly explain the use of the pins that are going to be used in the Wave generator module:

S1 and S2 pins

The PSLab device contains two pins (S1, S2) which are capable of producing two independent analog waveforms (sine,  sawtooth) having different frequencies and phase offset. The frequency range is from 10Hz to 5Khz.

SQR1, SQR2, SQR3 and SQR4 pin

The SQR1 pin is used for producing the square waveform and all the SQ pins can be used together to produce four different PWM signal having the same frequency. These PWM signal can have a different duty cycle and phase.

CH1, CH2 and CH3 pin

The CH pins are used by the oscilloscope in the  PSLab android app to monitor waveform signals produced by the wave generator pins. They can be used together to simultaneously monitor multiple waveforms.

Setting up the Device

We need to connect the PSLab device with the mobile phone as shown in Figure 2 which can be done by following steps:

  1. Connect a micro USB(Mini B) to the PSLab device.
  2. Connect the other end of the micro USB cable to the OTG.
  3. Connect the OTG to the phone.
Figure 2 shows the connection of the PSLab device with the smartphone

Producing Waveforms

Now, once the device has been properly connected to the device (which is shown at the top right corner of the app), then in the instruments page scroll down to the Wave Generator card and click on it to open the WaveGenerator activity.

Figure 3 shows the instruments containing card view to all the instruments and icon to show device status

Here you will see a screen like shown in Figure 4 containing two monitors and a controlling panel with lots of buttons. Here the Waveform panel is used to control the S1 and S2 pins whose properties are shown on the left monitor screen and the Digital panel is used to control the SQR pins whose properties are shown on the right monitor screen.

Figure 4 shows the UI of the Wave Generator Activity

For sine/sawtooth wave:

Connect the S1 pin to the CH1 pin using a connecting wire, then in the Waveform panel select the Wave1 button, choose the type of waveform(either sine or sawtooth), then click on the Freq button to change the frequency of the wave, then use the Seek bar or the up/down arrow buttons to change the value of frequency and then press the set button to set the frequency for the S1 pin as shown below:

Figure 5 The GIF shows the setting of the properties of the W1 pin in the UI

Now, click the view button at bottom right corner, this will directly open the Oscilloscope provided by the PSLab android app .

Once the oscilloscope is open, check the CH1 pin from the panel in the bottom and we can see the sine wave in the monitor shown by the screen in Figure 6 and Figure 7

Figure 6 shows the screenshot of oscilloscope showing the sine wave
Figure 7 shows the screenshot of the oscilloscope showing sawtooth wave

Similarly, if you want to see two sine waves connect the S1 pin to the CH1 and connect the S2 pin to the CH2 channel , choose the wave-type for both pin, set the frequencies for both of the waves, here you can also set the phase difference between the two waves, for setting phase difference first click on Wave2 button it will enable the phase button, then click on the Phase button and set the value of phase with the help of the Seek bar.

For Square Wave

Connect the CH1 pin to the SQ1 pin, after making the connection head over to the Digital panel in the Wave Generator, ensure that the mode is selected to square, now click on the Freq button in the digital panel and set the frequency of the square wave with the help of Seek bar, then click on the Duty button and set the value of duty cycle for the square wave as shown below:

Figure 8 The GIF shows the setting of properties for producing square wave from SQ1 pin

Now, once the square wave has been set click on the view button, the oscilloscope will open then select the CH1 pin and you can see the square wave on the monitor as shown by the screen in Figure 9.

Figure 9 shows the screenshot of the square wave as shown in the oscilloscope

Thus we have produced different waveforms using PSLab wave generator module.

Resources

PSLab device pin diagram  – https://github.com/fossasia/pslab-artwork/blob/master/Sticker/pslabdesign.png

Youtube Video Screencast for Wave Generator – https://www.youtube.com/watch?v=NC2T5kElWbE&t=1s

Continue ReadingProducing Waveforms using Wave Generator module in the PSLab Android App

Creating an apk in the apk branch using Travis CI

All Android apps in FOSSASIA have an apk branch where after a pull request is merged a new apk gets created so that even people who do not know how to setup the app locally can access it. Let’s see how it is done.

Lets get started

Create a bash file in the scripts folder and name it upload-apk.sh

Here is all the code that you require to create an apk in the apk branch.

First thing that we need to do is setup git. So we’ll set the user name and email just like we do when we setup git for the first time in our own systems.

git config --global user.name "Travis CI"
git config --global user.email "noreply+travis@fossasia.org"

 

Next we will clone the apk branch of the repository and copy all the files that we need ie the apk and the JSON files.

git clone --quiet --branch=apk https://fossasia:$GITHUB_API_KEY@github.com/fossasia/open-event-android apk > /dev/null
cd apk
\cp -r ../app/build/outputs/apk/*/**.apk .
\cp -r ../app/build/outputs/apk/debug/output.json debug-output.json
\cp -r ../app/build/outputs/apk/release/output.json release-output.json

 

Next we will create a new branch that contains only the latest apk. After that we will add the APK and then commit all those changes. You can see that the current date and time are printed out in the commit message.

git checkout --orphan temporary

git add --all .
git commit -am "[Auto] Update Test Apk ($(date +%Y-%m-%d.%H:%M:%S))"

 

We will delete the current apk branch and then rename the current branch to apk. In the end we will force push to origin since histories are unrelated.

git branch -D apk
git branch -m apk

git push origin apk --force --quiet > /dev/null

 

If you have already integrated Travis CI in your repository then you just need to add this line your travis.yml file.

after_success:
- bash scripts/update-apk.sh

 

Now every time a PR gets merged in the repository a new apk file is created in the apk branch of your repository.

Resources

  1. Travis CLI – https://github.com/travis-ci/travis.rb#readme
  2. Travis official documentation – https://travis-ci.org/
Continue ReadingCreating an apk in the apk branch using Travis CI

Using Two-Way Data Binding in Open Event Organizer Android App:

Data Binding is the simple approach which relieves developers of repeated findViewById() calls. It is something that every developer must use if not using ButterKnife.

The Open Event Organizer Android App provides options to fill in an extensive set of details while creating an event, or any other entities. The problem at hand is that many of these options are common to many of these entities. For instance, currently the element date-time-picker and text fields are common to elements of different forms, as each one of them requires date-time checkboxes.

We need to be able to <include> a separate smaller and reusable layout file and bind event data to make the code shorter. This would help decreasing unnecessary code base and improving code readability.

We will see how using 2 way data binding and <include> tags in the small PR #929 reduced the code of 112 lines to just 9 lines:

Step 1: Configuration:

The very first step is to configure your project to enable data bindings in your
build.gradle (Module:app) file.

dataBinding should be included as follows:

android {
   // Rest of gradle file…
   dataBinding {
   enabled true
   }    // Rest of gradle file…
}

Step 2: Import and variable tags:

Data Binding uses the tag <data> to signify the data which will be referred to in lambda expressions inside the XML.

We also need to import any class, whose methods we need to use. This can be done using the <import> tag.

Finally, the <variable> tag is used to define any variables that will be referenced in the XML.

 

<data>
  <import type=”android.view.View” />
  <variable
      name=“date”
      type=”String” />
  <variable
      name=“label”
      type=”String“/>
</data>

Step 3: Binding the declared variables:

Data binding recognizes methods of the type set<variable>, where <variable> is event in our case.

We need to use  executePendingBindings();  so that any pending bindings are done and the UI of our app responds correctly as soon as the view data is updated.

@Override
public void showResult(Event event) {
  binding.setEvent(event);
  binding.executePendingBindings();
}

Step 4: Using the declared variables:

Making use of the declared variables is a very simple task and is as simple as a java statement. You can do almost everything that’s possible in the java file, the only constraint being that the used variables are declared in the xml and binded appropriately.

Most of the data binding expressions use data binding to condense the expression to its smallest possible form.

<LinearLayout
  android:layout_width=“match_parent”
  android:layout_height=“wrap_content”
  android:padding=“@dimen/spacing_extra_small”
  android:orientation=“horizontal”
  android:visibility=“@{ picker.checked ? View.VISIBLE : View.GONE }”>

2 Way Data Binding

In case of the Organizer App, we are using 2 way data binding.

Data Binding allows us to do much more than just set text in TextView or create listener in Button. If we want to use EditText and automatically update text variable in java code, we need to use observable fields and two way binding.

Thus, most variables like date, event that we are binding, are Observable fields.

* Sometimes there’s a use case of using a variable declared in another layout file.

For example, in:

<org.fossasia.openevent.app.ui.views.DatePicker
  style=“?attr/borderlessButtonStyle”
  android:layout_width=“wrap_content”
  android:layout_height=“wrap_content”
  android:textColor=“@color/purple_500”
  app:value=“@={ date }” />

The variable date isn’t binded in the java file but the xml files which include the layout time_picker.xml

Using the <include> tag:

The include tag is very simple to use, and we can simply bind the date and label element. The event_create_form.xml binds the variable using the bind attribute like this:

<include
  layout=“@layout/time_picker”
  bind:date=“@={ event.startsAt }”
  bind:label=“@{ @string/starts_at }”/>

The most common error you will face:

Often, when there’s something wrong with the XML, the most common error you will face is:

“Cannot resolve Data Binding class…”

This error is because Android Studio couldn’t generate the Data Binding class for your XML file because of some error. Presently, it doesn’t give much details about what’s wrong, so you’ll have to look for the errors yourselves.

The most common mistake newbie developers make is forgetting to bind the variables appropriately.

References:

Android Developer Guide:

https://developer.android.com/topic/libraries/data-binding/

Continue ReadingUsing Two-Way Data Binding in Open Event Organizer Android App:

Making Zoom View in PSLab Android app

This blog demonstrates how to make a zoom view in an Android app by taking example from one made in PSLab Android app. It will mainly reflect the work done under PR #1117 in PSLab Android repository. The demonstration shown in this blog is for zooming a complete layout. But individual components of a layout can also be given this zoom effect.

How to make a zoom view?

Below is a step by step guide on how to implement a zoom view in an Android app :

  • First make a  Zoom Layout class in Android Project which will further include GestureDetector, MotionEvent, etc.
  • Now extend the Zoom Layout class from a base layout provided by Android i.e. Relative Layout, Linear Layout, etc. as per need because we need to give zoom effect to a complete layout. In this demonstration, I will use the Relative Layout class as my base class.
  • Also to detect the gestures made by a user, we need to implement the ScaleGestureDetector.OnScaleGestureListener class. So, finally, the class implementation will look like this
public class ZoomLayout extends RelativeLayout implements ScaleGestureDetector.OnScaleGestureListener {
}
  • Now make default constructors and declare variables to define the range of the minimum and maximum possible zoom, coordinates before drag, coordinates after drag, etc.
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 4.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
private float startX = 0f;
private float startY = 0f;
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;

public ZoomLayout(Context context) {
   super(context);
   init(context);
}

Here startX and startY are the initial coordinates of the layout, dx and dy are the new coordinates of the layout and prevDx and prevDy are the coordinates of the previous location of the layout. Also, mode is the current mode of the gesture which will be further elaborated upon in coming steps, and all other remaining variables are for scaling the screen on gesture movements. Also, init(context) is a method which will be explained in step 5.

  • Now, we will make a method named init() to initiate the process of scaling the layout on gesture detection.
public void init(Context context) {
        final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
        this.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        if (scale > MIN_ZOOM) {
                            mode = Mode.DRAG;
                            startX = motionEvent.getX() - prevDx;
                            startY = motionEvent.getY() - prevDy;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == Mode.DRAG) {
                            dx = motionEvent.getX() - startX;
                            dy = motionEvent.getY() - startY;
                        }
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        mode = Mode.ZOOM;
                        break;
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = Mode.DRAG;
                        break;
                    case MotionEvent.ACTION_UP:
                        mode = Mode.NONE;
                        prevDx = dx;
                        prevDy = dy;
                        break;
                    default:
                        mode = Mode.NONE;
                        prevDx = dx;
                        prevDy = dy;
                        break;
                }
                scaleDetector.onTouchEvent(motionEvent);

                if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                    float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
                    float maxDy = (child().getHeight() - (child().getHeight() / scale)) * scale;
                    dx = Math.min(Math.max(dx, -maxDx), maxDx);
                    dy = Math.min(Math.max(dy, -maxDy), maxDy);
                    applyScaleAndTranslation();
                }
                return true;
            }
        });
    }

The detailed explanation of the above code snippet is as follows:

  1. scaleDetector – A gesture detector variable to store the scaling of the screen i.e. how much the screen is zoomed
  2. onTouch() – It is the main method handling the calculations for zooming the layout and setting the position of the zoomed layout. The view attribute is the current view of the layout and the motionEvent attribute handles the different task for different gestures made by a user.

Here the mode variable is used to define one of the three gestures i.e. NONE, DRAG or ZOOM where

  1. NONE – No gesture detected on the screen
  2. DRAG – Sliding gestures are made
  3. ZOOM – Pinch gesture is made

Also, a detailed explanation of the motion events used in the switch case can be found out in the resources [1].

After the switch case, the if statement is used to do calculations based on the current child in focus and the previous coordinates if and only if the zoom hasn’t reached the maximum limit and the view is dragged to see the zoomed contents. Method getParent().requestDisallowInterceptTouchEvent(true) is used to disable the scroll effect of the parent layout if any. In this case, the zoomed layout is inside a bottom sheet and so by using this method, the bottom sheet isn’t closed on swipe down gesture.

  • Now create applyScaleAndTransition() method and child() method used in step 5.
private View child() {
        return getChildAt(0);
    }

This method is used to return the current child layout in focus i.e. visible on the screen.

private void applyScaleAndTranslation() {
        child().setScaleX(scale);
        child().setScaleY(scale);
        child().setTranslationX(dx);
        child().setTranslationY(dy);
    }

This method is used to apply the final calculations that are done in step 5 to the child layout in focus.

So, now the Zoom Layout is ready for use and can be used as same as we use the Relative Layout in the XML files. The final output produced by using the Zoom Layout as a child of bottom sheet in PSLab Android app is as shown in figure 1.

Figure 1. Demonstration of Zoom Layout made in PSLab Android app

Resources

  1. https://developer.android.com/reference/android/view/MotionEvent – Documentation of motion event gestures in android
Continue ReadingMaking Zoom View in PSLab Android app

Stepper Motors Experiment with PSLab

PSLab device is capable of building up a complete science lab almost anywhere. While the privilege is mostly taken by high school students and teachers to perform scientific experiments, electronic hobbyists can greatly be influenced from the device. One of the usages is to test and debug sensors and other electronic components before actually using them in their projects. This blog will explain how steppers motors can be used with PSLab.

A stepper motor is an electromechanical device which converts electrical power into mechanical power. Also it is a brushless, synchronous electric motor that can divide a full rotation into an expansive number of steps. The stepper motor uses the theory of operation for magnets to make the motor shaft turn a precise distance when a pulse of electricity is provided. Stepper motors are similar to switched reluctance motors. [1]


Figure 1: Showing the working of a stepper motor [4]                                                      

Figure 1 shows the animation of a simplified stepper motor. Unlike a brushless DC motor which rotates continuously when a fixed DC voltage is applied to it, a step motor rotates in discrete step angles as shown in the above figure.

How Stepper Motors Work?

  • Stepper Motor works on the principle of electromagnetism.
  • Stepper motors consist of a permanent magnetic rotating shaft, called the     rotor, and electromagnets on the stationary portion that surrounds     the motor, called the stator.
  • Figure 1 illustrates one complete rotation of a stepper motor. At position 1, we can see that the rotor is beginning at the upper     electromagnet, which is currently active (has voltage applied to it).
  • To move the rotor clockwise (CW), the upper electromagnet is deactivated and the right electromagnet is activated, causing the rotor to move 90 degrees CW, aligning itself with the active magnet.
  • This process is repeated in the same manner at the south and west     electromagnets until we once again reach the starting position.

           Figure  (2): Showing different stages of stepper motors’ working cycle [3]

What are the most common reasons to choose stepper motors over other types? [2]

  1. Positioning     Since steppers move in precise repeatable steps, they excel in applications requiring precise positioning such as 3D printers, CNC, Camera platforms and X,Y Plotters. Some disk drives also use stepper motors to position the read/write head.
  2. Speed Control – Precise increments of movement also allow for excellent control of rotational speed for process automation and robotics.
  3. Low Speed Torque – Normal DC motors don’t have very much torque at low speeds. A Stepper motor has maximum torque at low     speeds, so they are a good choice for applications requiring low speed with high precision.

Applications of Stepper Motors [2]

  1. Industrial Machines – Stepper motors are used in automotive gauges and machine tooling automated production equipments.
  2. Office Equipments – Stepper motors are incorporated inside PC based scanning equipment, data storage tape drives, optical disk drive head driving mechanism, printers, bar-code printers, scanners
  3. Medical – Stepper motors are used inside medical scanners, samplers, and also found inside digital dental photography, fluid pumps, respirators and blood analysis machinery.
  4. Consumer Electronics – Stepper motors in cameras for automatic digital camera focus and zoom functions.

       

Figure  (3) :Figure showing stepper motors being used in robo -arms [5]

Implementation of Stepper Motor in PSLab

Figure  (4) :A screenshot of Stepper Motor Experiment using PSLab Android App.

  • In the PSLab the stepper motor experiment is implemented to tell the user what a stepper motor is  and how to use it.
  • There is one field to enter the number of steps i.e the breaks in one one rotation which the stepper motor will have.
  • Using PSLab device experiment “Stepper Motor”, a user can acquire any number of steps just by entering the step value in the text box.
  • The following code is implemented for executing the function.
private void setSteps() {
         int stepCount = Integer.parseInt(steps.getText().toString());
         if (stepCount > 0) {
               stepForward(stepCount);
         } else {
               stepBackward(stepCount);
         }
}
  • The other two buttons are designed for choosing the direction in which the motor  will rotate.
  • The following code is for the backward function.
private void stepBackward(final int steps) {
    java.lang.Runnable runnable = new java.lang.Runnable() {
        @java.lang.Override
        public void run() {
            scienceLab.stepBackward(steps, 100);
        }
    };
    new java.lang.Thread(runnable).start();
}
  • Thus when the stepper motor  is connected to the PSLab device and the android application experiment is made to run, the stepper motor will rotate accordingly.

Resources

  1. https://learn.adafruit.com/all-about-stepper-motors/what-is-a-stepper-motor
  2. https://www.elprocus.com/stepper-motor-types-advantages-applications/
  3. https://www.imagesco.com/articles/picstepper/02.html
  4. https://en.wikipedia.org/wiki/Stepper_motor
  5. https://www.instructables.com/id/Robot-Arm-MK2-Plus-Stepper-Motor-Used/
Continue ReadingStepper Motors Experiment with PSLab

Implementing Custom Date and Time Picker with 2-way Data Binding Support

The Data binding library is one of the most popular libraries among the android developers. We have been using it in the Open Event Organiser Android app for building interactive UI’s for some time now. The Open Event Organiser Android App is the Event management app for organizers using the Open Event Platform. This blog explains how we implemented our own custom Date and Time picker with 2-way data binding support using the Data binding framework.

Why custom picker ?

One specific requirement in the app is to have a button, clicking on that button should open a DatePicker which would allow the user to select the date. A similar behaviour was required to allow the user to select the time as well. In order to handle this requirement we were using Binding Adapters on Button. For eg. the following Binding Adapter allowed us to define a property date on a button and set an Observable String as it’s value. We implemented a similar Binding Adapter for selecting time as well.

@BindingAdapter("date")
public static void bindDate(Button button, ObservableField<String> date) {
    String format = DateUtils.FORMAT_DATE_COMPLETE;

    bindTemporal(button, date, format, zonedDateTime ->
        new DatePickerDialog(button.getContext(), (picker, year, month, dayOfMonth) ->
                setPickedDate(
                    LocalDateTime.of(LocalDate.of(year, month + 1, dayOfMonth), zonedDateTime.toLocalTime()),
                    button, format, date),
                zonedDateTime.getYear(), zonedDateTime.getMonthValue() - 1, zonedDateTime.getDayOfMonth()));
  }

It calls the bindTemporal method which takes in a function along with the button, date and the format and does two things. First, it sets the value of the date as the text of the button. Secondly, it attaches a click listener to the button and applies the function passed in as the argument when clicked. Below is the bindTemporal method for reference:

private static void bindTemporal(Button button, ObservableField<String> date, String format, Function<ZonedDateTime, AlertDialog> dialogProvider) {
        if (date == null)
            return;

        String isoDate = date.get();
        button.setText(DateUtils.formatDateWithDefault(format, isoDate));

        button.setOnClickListener(view -> {
            ZonedDateTime zonedDateTime = ZonedDateTime.now();
            try {
                zonedDateTime = DateUtils.getDate(isoDate);
            } catch (DateTimeParseException pe) {
                Timber.e(pe);
            }
            dialogProvider.apply(zonedDateTime).show();
        });
    }

It was working pretty well until recently when we started getting deprecation warnings about using Observable fields as a parameter of Binding Adapter. Below is the full warning:

Warning:Use of ObservableField and primitive cousins directly as method parameters is deprecated and support will be removed soon. Use the contents as parameters instead in method org.fossasia.openevent.app.common.app.binding.DateBindings.bindDate

The only possible way that we could think of was to pass in regular String in place of Observable String. Now if we pass in a regular String object then the application won’t be reactive. Hence we decided to implement our own custom view to resolve this problem.

Custom Date and Time Picker

We decided to create an Abstract DateTimePicker class which will hold all the common code of our custom Date and Time pickers. It is highly recommended that you go through this awesome blog post first before reading any further. We won’t be going through the details already explained in the post.

Following are the important features of this Abstract class:

  1. It extends the AppCompatButton class.
  2. It stores an ObservableString named value and an OnDateTimeChangedListener as it’s field. We will discuss the change listener later in the article.
  3. It implements the three mandatory constructors and calls it’s super method. It also calls the init method which sets the current date and time as the default.
  4. It has a bindTemporal method which is the same as we discussed earlier.
  5. It has a setPickedDate method which sets the selected date/time as the text for the button so that users can see the selected date/time on the button itself. Moreover it notifies the change listener about the change in date if attached.
  6. It has an abstract method called setValue. It will be implemented in the sub classes and used to set the date or time value for the field named value.

You can check the full implementation here.

The OnDateTimeChangedListener which we mentioned above is an extremely simple interface. It defines a simple method onDateChanged which takes in the selected date as the argument.

public interface OnDateTimeChangedListener {
    void onDateChanged(ObservableString newDate);
}

Let’s have a look at the implementation of the DatePicker class. The key features of this class are:

  1. It extends the AbstractDateTimePicker class and implements the necessary constructors calling the corresponding super constructor.
  2. It implements the method setValue which sets the date or time passed in to the field value. It also calls the bindTemporal method of the super class.

public class DatePicker extends AbstractDateTimePicker {
    public DatePicker(Context context) {
        super(context);
    }

    public DatePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public DatePicker(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

  public void setValue(String value) {
        ObservableString observableValue = getValue();
        if (observableValue.get() == null || !TextUtils.equals(observableValue.get(), value)) {
            observableValue.set(value);
            String format = DateUtils.FORMAT_DATE_COMPLETE;

            bindTemporal(value, format, zonedDateTime ->
                new DatePickerDialog(this.getContext(), (picker, year, month, dayOfMonth) ->
                    setPickedDate(
                        LocalDateTime.of(LocalDate.of(year, month + 1, dayOfMonth), zonedDateTime.toLocalTime()), format),
                    zonedDateTime.getYear(), zonedDateTime.getMonthValue() - 1, zonedDateTime.getDayOfMonth()));
        }
    }
}

Next we discuss the BindingAdapter and the InverseBindingAdapter for the custom DatePicker which allows the data binding framework to set the action to be performed when date changes and get the date from the view respectively.

@BindingAdapter(value = "valueAttrChanged")
public static void setDateChangeListener(DatePicker datePicker, final InverseBindingListener listener) {
        if (listener != null) {
            datePicker.setOnDateChangedListener(newDate -> listener.onChange());
        }
    }

@InverseBindingAdapter(attribute = "value")
public static String getRealValue(DatePicker datePicker) {
    return datePicker.getValue().get();
}

Now in order to use our view, we can simply define it in the layout file as shown below:

<org.fossasia.openevent.app.ui.views.DatePicker
                    style="?attr/borderlessButtonStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@color/purple_500"
                    app:value="@={ date }" />

The key thing to notice is the use of @= instead of @ which denotes two way data binding.    

Conclusion

The Android Data binding framework is extremely powerful and flexible at the same time. We can use it for our custom requirements as shown in this article.

References

 

 

 

 

 

Continue ReadingImplementing Custom Date and Time Picker with 2-way Data Binding Support

Working with Logic Analyzer in PSLab Android app

This blog demonstrates the working of Logic Analyzer instrument available in PSLab Android app. It also includes a detailed description of the features available in the Logic Analyzer instrument along with a step by step guide on how to work with it which will be beneficial to first-time users of the PSLab application.

The functionality of the Logic Analyzer available in PSLab Android app is same as that in PSLab Desktop App. So, it would be easy for a user of PSLab Desktop Application to get acquainted with this Logic Analyzer. The only difference in this instrument is the changed and attractive UI which makes working with it very easy.

Why use Logic Analyzer?

The Logic Analyzer instrument provides the functionality of capturing and plotting the digital waves on the screen so that it would be easy for a user to determine the time relationship between different waves. So, this instrument would be very useful while working with timing diagrams, protocol decodes, state machines traces, assembly language, or with source-level software.

How to generate different digital pulses in the PSLab app?

Logic Analyzer needs to be provided with some input of digital pulses among whom time relationship is to be found out. Digital pulses generated from different systems can be directly provided as input to the Logic Analyzer for analyzing. But PSLab provides a functionality to generate digital pulses up to some constrained frequency.

Following are the steps to generate different digital waves in PSLab Android application :

  • Open PSLab Android application and click on the Wave Generator tile as shown in figure 1. After opening the instrument, the screen will look as shown in figure 2.

Figure 1. Wave Generator instrument tile available in PSLab Android app

Figure 2. The main screen of the Wave Generator instrument

  • Click on the MODE button to change the mode to PWM. The screen will look as shown in figure 3.

Figure 3. PWM mode in Wave Generator

  • PSLab device provides generation of maximum four digital waves at once. In this example, I will proceed by utilizing only two pins i.e. SQR1and SQR2 (where SQR = Acronym of square wave generator and the number next to it is the pin ID available on the PSLab device) to demonstrate the working of Two Channel Mode in Logic Analyzer. Set the duty cycles and frequency for the selected pins as desired (try to keep all the duty cycles different from each other to understand the process of measurement easily).

NOTE: User can also set phase angle for different waves but I will proceed with defaults.

How to analyze the generated waves in Logic Analyzer?

  • Now go back and select the Logic Analyzer tile as shown in figure 4 from the list of available instruments. A screen as shown in figure 5 should open.

Figure 4. Tile of Logic Analyzer instrument available in the PSLab app

Figure 5. The main screen of the Logic Analyzer instrument

On the right-hand side, you can see a slider whose initial value is SELECT which shows the information on how to use the slider below it. Below the Channel Selection area is the Analyze button used to fetch and plot the data which is generated or provided to the respective Logic Analyzer pins i.e. ID1, ID2, ID3, and ID4.

The blank area on the left is where the graph will be plotted after fetching data points. Below it is the Axis Indicator used to indicate the position of the highlighter so that time measurement can be done easily. To the right of the Axis Indicator is a small light which indicates the status of the device. It turns GREEN if the device is connected else it remains in RED.

  • In this blog, I will demonstrate the Two Channel Mode. But all the other available modes need the same implementation by only varying the number of pins in use. So, slide to 2 in the Carousel View and a screen as shown in figure 6 will pop up.

Figure 6. Two Channel Mode in Logic Analyzer

  • Connect the wires on the PSLab device as shown in Figure 7.

Figure 7. Connecting wires on PSLab

NOTE: The Logic Analyzer pins used in this demonstration are ID1 and ID2. But any IDx pin can be chosen for analysis. But try to maintain the selected choice throughout the implementation.

  • Now from the Channel Selection area, select the channel for the first card to  ID1 (default) and that for the second card to ID2. For Edges Selection, maintain the defaults.

NOTE: There are several options available for plotting the digital waves besides the default selected i.e.

  1. Every Edge – Plot every edge of the signal
  2. Falling Edges – Plot only falling edges of the signal (When a signal comes from 1 to 0 state)
  3. Rising Edges Only – Plot only rising edges of the signal (When a signal comes from 0 to 1 state)
  4. Disabled – Don’t plot the selected wave
  • After Channel Selection, press the Analyze button to plot the data. On pressing the Analyze button, a circular loading sign will appear showing that the data is being fetched and converted to data that can be plotted. As soon as the data is ready to be plotted, the loading sign vanishes and the graph appears as shown in figure 8.

Figure 8. GIF showing the loading and analyzing processes

  • The time relationship between the plotted data can be found out by clicking over the rising/falling edges and noting the time shown in the Axis Indicator as shown in figure 8.
  • An example of Edge Selection is shown in figure 9.

Figure 9. Example of Edge Selection option

Here, EVERY FALLING EDGE option is selected for the ID1 channel and EVERY RISING EDGE option is selected for the ID2 channel.

So in this way, the Logic Analyzer instrument available in PSLab Android application can be used to ease out the process of calculating the time interval between different edges for different/same digital pulse/s.

Resources

  1. PSLab Android Application – https://github.com/fossasia/pslab-android (Link to repo)
  2. PSLab device pins sticker – https://github.com/fossasia/pslab-artwork/blob/master/Sticker/pslabdesign.png
Continue ReadingWorking with Logic Analyzer in PSLab Android app

Implementing the discrete Seekbar for Wave Generator

The Wave Generator instrument in PSLab Android app allows us to produce waveforms having different values of properties like frequency, duty, phase etc.

The range of these properties allowed by PSLab Device are :

Table showing the range of properties that can be set for waves by PSLab device
Wave Property Range
Min Max Step Size
Frequency 10 Hz 5000 Hz 1 Hz
Phase 360°
Duty 10% 100% 10%

We can set these values using the up/down arrow buttons provided by the wave generator but the problem is that the range of values is very high and least counts are small so it is convenient to set the values using only the up and down arrow buttons.

Therefore we need something that could allow us to directly set any value of our choice while keeping the UI interactive.

The solution to this problem – “Discrete Seekbar”. It contains a slider having points at equal intervals and whose length represents the range of the values and a head that slides over the slider and is used to select a specific value from a range of values.

I have included the discrete Seekbar in Wave Generator by using a third-party library if you want to add Seekbar directly you can do that by directly using the default Seekbar widget provided by Android SDK and setting the following attribute in as shown below.

android:theme = “@style/Widget.AppCompat.SeekBar.Discrete”

Refer to this post[2] for implementing Seekbar directly without an external library.

The reason I chose this library is that:-

  • It offers various implementation of different types of Seekbar like discrete and continuous.
  • Implementation of Seekbar is simpler and it offers various customizations like thumb color, track color, tick text etc.  

In following steps I will implement the discrete Seekbar:

Step 1 Adding the dependency

For this project, I will be using an external library “IndicatorSeekbarLibrary” by Warkiz[1], for adding the dependency we need to include the following code in our build.gradle file.

dependencies{
implementation 'com.github.warkiz.widget:indicatorseekbar:2.0.9'
}

Step 2 Including the Seekbar in layout

For this step, we need to add the Seekbar widget using <com.warkiz.widget.IndicatorSeekBar> XML tag in our wave generator layout file to include the Seekbar in our layout as shown in the code below:

<com.warkiz.widget.IndicatorSeekBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:isb_max="5000"
    app:isb_min="0"
    app:isb_ticks_count="5"
    app:isb_thumb_color="@color/color_green"
    app:isb_thumb_size="20dp"
    app:isb_track_background_color="@color/color_gray"
    app:isb_track_background_size="2dp"
    app:isb_track_progress_color="@color/color_blue"
    app:isb_track_progress_size="4dp" />

Some important attributes used above:

app:isb_max : defines the max value that can be achieved by the Seekbar.

app:isb_min :  defines the min value that can be achieved by the Seekbar

app:isb_ticks_count: no. of ticks(interval) that has to be shown on the slider

We can see different components of Seekbar like track, indicator, thumb, tick of SeekBar in the following diagram[2].

Figure 1 depicts the different attributes of the slider
(Source – https://github.com/warkiz/IndicatorSeekBar/blob/master/README.md)

Step 3 Attaching the listener to the Seekbar in Java file

In this step we need to attach the listener to the Seekbar to record changes in the Seekbar made by the user, for this we will create a new listener with the help of onSeekBarChangeListener interface and attach it with the Seekbar as shown in following code

IndicatorSeekBar seekbar = (IndicatorSeekBar) findViewbyId(R.id.seekbar);

seekBar.setOnSeekChangeListener(new OnSeekChangeListener() {
            @Override
            public void onSeeking(SeekParams seekParams) {
                /* called when the user is sliding the thumb */
            }

            @Override
            public void onStartTrackingTouch(IndicatorSeekBar seekBar) {
                /* called when the sliding of thumb is started */
            }

            @Override
            public void onStopTrackingTouch(IndicatorSeekBar seekBar) {
                /* called when the sliding of thumb stops */
            }
        });

After following all the above steps, I  implemented the Seekbar shown in Figure 2 below in my wave generator and now it becomes really easy to set different values of properties for without having to continually press the up/down button.

Figure 2 shows the Seekbar included in wave generator beside up/down arrow button

Resources

  1. warkiz/IndicatorSeekBar library  – Github Repo of the Indicator SeekBar library
  2. http://nileshsenta.blogspot.com/2016/10/discrete-seekbar-without-third-party.html – Blog by Nilesh Shenta on how to implement discrete without third party library

 

Continue ReadingImplementing the discrete Seekbar for Wave Generator