Saturday 31 December 2016

Error: '…' does not name a type

Most solutions to this problem talk about the headers. But the first reference below mentioned something that inspire me and solved my problem --  circular inclusion. 

There are many references about it online but I like this one:
http://stackoverflow.com/questions/625799/resolve-header-include-circular-dependencies

The way to think about this is to "think like a compiler".
Imagine you are writing a compiler. And you see code like this.
// file: A.h
class A {
  B _b;
};

// file: B.h
class B {
  A _a;
};

// file main.cc
#include "A.h"
#include "B.h"
int main(...) {
  A a;
}
When you are compiling the .cc file (remember that the .cc and not the .h is the unit of compilation), you need to allocate space for object A. So, well, how much space then? Enough to store B! What's the size of B then? Enough to store A! Oops.
......you can read on.

ref:
http://stackoverflow.com/questions/3961103/error-does-not-name-a-type (inspired by this)
http://stackoverflow.com/questions/2133250/does-not-name-a-type-error
http://stackoverflow.com/questions/8470822/error-x-does-not-name-a-type

http://stackoverflow.com/questions/625799/resolve-header-include-circular-dependencies

Tuesday 27 December 2016

Android: Send “POST” JSON Data to Server

The following blog provide a great example of posting JSON data to Server:

                               http://hmkcode.com/android-send-json-data-to-server/


But there are a few problems to be solved before successfully running.

(1) Check:
http://boriscoding.blogspot.ca/2016/12/fail-to-import-orgapachehttpxxx-stuff.html

(2) Check:
http://boriscoding.blogspot.ca/2016/12/error-method-gettext-must-be-called.html
And my MainActivity.java


import android.support.v7.app.AppCompatActivity;import android.os.Bundle;
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import org.apache.http.HttpResponse;import org.apache.http.client.HttpClient;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.DefaultHttpClient;import org.json.JSONObject;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.os.AsyncTask;import android.util.Log;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import android.app.Activity;
public class MainActivity extends Activity implements OnClickListener {

    TextView tvIsConnected;    EditText etName,etCountry,etTwitter;    Button btnPost;
    Person person;    String got_etName,got_etCountry,got_etTwitter;    @Override    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);
        // get reference to the views        tvIsConnected = (TextView) findViewById(R.id.tvIsConnected);        etName = (EditText) findViewById(R.id.etName);        etCountry = (EditText) findViewById(R.id.etCountry);        etTwitter = (EditText) findViewById(R.id.etTwitter);        btnPost = (Button) findViewById(R.id.btnPost);
        // check if you are connected or not        if(isConnected()){
            tvIsConnected.setBackgroundColor(0xFF00CC00);            tvIsConnected.setText("You are conncted");        }
        else{
            tvIsConnected.setText("You are NOT conncted");        }

        // add click listener to Button "POST"        btnPost.setOnClickListener(this);
    }

    public static String POST(String url, Person person){
        InputStream inputStream = null;        String result = "";        try {

            // 1. create HttpClient            HttpClient httpclient = new DefaultHttpClient();
            // 2. make POST request to the given URL            HttpPost httpPost = new HttpPost(url);
            String json = "";
            // 3. build jsonObject            JSONObject jsonObject = new JSONObject();            jsonObject.accumulate("name", person.getName());            jsonObject.accumulate("country", person.getCountry());            jsonObject.accumulate("twitter", person.getTwitter());
            // 4. convert JSONObject to JSON to String            json = jsonObject.toString();
            // ** Alternative way to convert Person object to JSON string usin Jackson Lib            // ObjectMapper mapper = new ObjectMapper();            // json = mapper.writeValueAsString(person);
            // 5. set json to StringEntity            StringEntity se = new StringEntity(json);
            // 6. set httpPost Entity            httpPost.setEntity(se);
            // 7. Set some headers to inform server about the type of the content            httpPost.setHeader("Accept", "application/json");            httpPost.setHeader("Content-type", "application/json");
            // 8. Execute POST request to the given URL            HttpResponse httpResponse = httpclient.execute(httpPost);
            // 9. receive response as inputStream            inputStream = httpResponse.getEntity().getContent();
            // 10. convert inputstream to string            if(inputStream != null)
                result = convertInputStreamToString(inputStream);            else                result = "Did not work!";
        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());        }

        // 11. return result        return result;    }

    public boolean isConnected(){
        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Activity.CONNECTIVITY_SERVICE);        NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();        if (networkInfo != null && networkInfo.isConnected())
            return true;        else            return false;    }
    @Override    public void onClick(View view) {

        switch(view.getId()){
            case R.id.btnPost:
                if(!validate())
                    Toast.makeText(getBaseContext(), "Enter some data!", Toast.LENGTH_LONG).show();                // call AsynTask to perform network operation on separate thread                new HttpAsyncTask().execute("http://hmkcode.appspot.com/jsonservlet");                break;        }

        got_etName = etName.getText().toString();        got_etCountry = etCountry.getText().toString();        got_etTwitter = etTwitter.getText().toString();    }

    // Helps in creating the connection in a separate thread so the UI will not freeze.    private class HttpAsyncTask extends AsyncTask<String, Void, String> {
        @Override        protected String doInBackground(String... urls) {

            person = new Person();            person.setName(got_etName);            person.setCountry(got_etCountry);            person.setTwitter(got_etTwitter);
            //person.setName(etName.getText().toString());            //person.setCountry(etCountry.getText().toString());            //person.setTwitter(etTwitter.getText().toString());
            return POST(urls[0],person);        }
        // onPostExecute displays the results of the AsyncTask.        @Override        protected void onPostExecute(String result) {
            Toast.makeText(getBaseContext(), "Data Sent!", Toast.LENGTH_LONG).show();        }
    }

    // Helper method to check that data is not empty before send the request.    private boolean validate(){
        if(etName.getText().toString().trim().equals(""))
            return false;        else if(etCountry.getText().toString().trim().equals(""))
            return false;        else if(etTwitter.getText().toString().trim().equals(""))
            return false;        else            return true;    }

    // Helper method to convert inputstream to String    private static String convertInputStreamToString(InputStream inputStream) throws IOException{
        BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));        String line = "";        String result = "";        while((line = bufferedReader.readLine()) != null)
            result += line;
        inputStream.close();        return result;
    }
}




Error: “Method getText() must be called from the UI thread, currently inferred thread is worker.”





ref:
http://stackoverflow.com/questions/32011996/method-gettext-must-be-called-from-the-ui-thread-android-studio    (I did this)
http://stackoverflow.com/questions/32324769/error-method-gettext-must-be-called-from-the-ui-thread-currently-inferred-t
http://stackoverflow.com/questions/32568340/android-studio-error-method-gettext-must-be-called-from-the-ui-thread-curre

Sunday 18 December 2016

Fail to Import org.apache.http.XXX stuff in Android Studio

I was just trying to import these:

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;

but they went grey and says "unused ...". This is because HttpClient is not supported any more in sdk 23. You have to use URLConnection or downgrade to sdk 22 (compile 'com.android.support:appcompat-v7:22.2.0')

Solution:
If you need sdk 23, add this to Gradle Scripts/build.gradle(Module:app)
          useLibrary 'org.apache.http.legacy'

It looks like the following:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.0"
    useLibrary 'org.apache.http.legacy'
    defaultConfig {
    applicationId "com.example.xxxx.xxxxxxxxxxample"
    minSdkVersion 15
    targetSdkVersion 25
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }

.....................

}

Then there will be a pop up saying something changed in Gradle, do you want to Sync? And press Sync, it will re-compile everything and the errors are gone.


ref:
http://stackoverflow.com/questions/32153318/httpclient-wont-import-in-android-studio

Saturday 17 December 2016

Particle Photon Setup Problem: Flashing Cyan with a Quick Red Burst(Bad Key Issue)

Just didn't know why the Photon cannot connect to the cloud and keeps flashing cyan (with some very quick red burst sometimes). But the Particle team has been really helpful! Check this topic:

https://community.particle.io/t/photon-setup-flashing-cyan-with-a-quick-red-burst-now-orange-burst-solved/12118/70

To sum up:

particle keys new particle keys load device.pem particle keys send <device_id> device.pub.pem // grab this file https://s3.amazonaws.com/spark-website/cloud_public.der particle keys server cloud_public.der

Then try to put the device into Safe Mode and it CAN finally connected to the cloud again!!!
(Dec 17 2016)

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

This shit happened again Apr. 20 2017!!!!!!!!!

This time I fixed this with a easier way:

(1) Put the device into DFU

(2) particle keys doctor DEVICE_ID

Found DFU device 2b04:d008
Found DFU device 2b04:d008
New Key Created!
Found DFU device 2b04:d008
Found DFU device 2b04:d008
Saved!
spawning dfu-util -d 2b04:d008 -a 1 -i 0 -s 34:leave -D XXXYYYZZZDeviceID_rsa_new.der
dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 2b04:d008
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #1 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 4096
DfuSe interface name: "DCT Flash   "
Downloading to address = 0x00000022, size = 608
Download [=========================] 100%          608 bytes
Download done.
File downloaded successfully
Saved!
attempting to add a new public key for device XXXYYYZZZDeviceID
submitting public key succeeded!
Okay!  New keys in place, your device should restart.


(3) particle keys server

Found DFU device 2b04:d008
spawning dfu-util -d 2b04:d008 -a 1 -i 0 -s 2082 -D /usr/local/lib/node_modules/particle-cli/keys/rsa.pub.der
dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 2b04:d008
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #1 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 4096
DfuSe interface name: "DCT Flash   "
Downloading to address = 0x00000822, size = 512
Download [=========================] 100%          512 bytes
Download done.
File downloaded successfully
Okay!  New keys in place, your device will not restart.


(4) particle flash --usb tinker

Found DFU device 2b04:d008
spawning dfu-util -d 2b04:d008 -a 0 -i 0 -s 0x080A0000:leave -D /usr/local/lib/node_modules/particle-cli/binaries/p1_tinker.bin
dfu-util 0.8

Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc.
Copyright 2010-2014 Tormod Volden and Stefan Schmidt
This program is Free Software and has ABSOLUTELY NO WARRANTY
Please report bugs to dfu-util@lists.gnumonks.org

dfu-util: Invalid DFU suffix signature
dfu-util: A valid DFU suffix will be required in a future dfu-util release!!!
Opening DFU capable USB device...
ID 2b04:d008
Run-time device DFU version 011a
Claiming USB DFU Interface...
Setting Alternate Setting #0 ...
Determining device status: state = dfuIDLE, status = 0
dfuIDLE, continuing
DFU mode device DFU version 011a
Device returned transfer size 4096
DfuSe interface name: "Internal Flash   "
Downloading to address = 0x080a0000, size = 4740
Download [=========================] 100%         4740 bytes
Download done.
File downloaded successfully

Flash success!

ref:
https://community.particle.io/t/solved-photon-fast-blinking-cyan-with-a-random-red-burst/14359
https://community.particle.io/t/photon-setup-flashing-cyan-with-a-quick-red-burst-now-orange-burst-solved/12118/75
https://community.particle.io/t/photon-flashing-cyan-with-red-bursts-solved/25113/3


Thursday 1 December 2016

Compiling Using Particle CLI with Subfolders

I always like to keep things tidy and neat so I keep many things in subfolders such as ./sensors/xxxTemperature.cpp and #include them in the same way with relative directories. However, problems come after I updated my particle cli this morning (didn't happen before). The compiler started to tell me:
fatal error: No such file or directory ../build/target/user/platform-6xxxx

I tried with just one directory with everything in it and it worked, although I HATE it because it looks so fatty. "Stupid Particle" I said...

The first reference inspired me that Particle is actually making its compiler "smart" enough to search through all subfolders and we don't have to manually setup the relative directories. For example, if we have ./sensors/xxxTemperature.h, we usually write the include code:
#include "./sensors/xxxTemperature.h"

Now you can just (no...ONLY) follow the smart way by writing:
                                                   #include "xxxTemperature.h"

And the Particle Compiler could automatically search for it.

ref:
https://community.particle.io/t/subdirectories-not-compiling-in-cli-fixed/9283/5   (helped me.)
https://community.particle.io/t/compiling-using-cli-with-multiple-directories/24273
https://community.particle.io/t/multiple-folders-in-the-dev-ide-compile-errors-go-to-blank-file/18876