Electric train V2

Following the first version of the electric train : http://djynet.net/?p=731

After some weeks of works I’m proud to announce the Version 2 of the electric train:

TrainV2

Wifi capabilities

The train can now be control with Wifi. It creates a wifi hotspot at boot time allowing people to connect to access a UI with some commands. The Wifi hotspot creation is describe HERE

Web

The train now offers a Web UI which allows controlling it and seeing the camera broadcast. The UI is done in Angular JS (with Bootsrap Angular UI). The Web server used to render the page is a python one : Tornado.

In addition of the UI it offers REST API to control the train (which are called today by the UI but could be used for a native Android application). The Web creation setup is detail HERE (TODO).

Embedded camera

The train is now equipped with a camera (the official Raspberry camera). The camera stream is broadcast and available on the train Web UI. The camera broadcast setup is describe HERE

Raspberry Pi brain

I replace the Arduino board with a Raspberry Pi A+. This extra boost of power was needed to broadcast the camera stream and create a wifi hotspot.

UBEC Power source

The biggest surprise I had when creating the new version was lot of unexpected Raspberry Pi reboot. Every time I was starting to move the train the Raspberry Pi was rebooting. I quickly suspect it was due to the motor which either took too much current or create perturbation that the 7805 cannot handle by itself. I done some research to understand how this issue was usually handle in R/C world and find out that they already have the perfect solution : BEC.

It is used to power the command part of the RC model from the same source than the motor. It provides a smooth tension and is able to absorb the impact of the motors on the power source with use of self and capacitor (wikipedia link). Since it is standard component in R/C world you can buy them pretty easily on the Web :

UBEC

The final result is visible in this video : TODO

Raspberry Pi Wifi hotspot

I need my Raspberry Pi to create its own private dedicated Wi-Fi network so that people can connect on it an access some service it provide (like camera broadcast).

To do so I’ve done some search and find out several tutorial to do it (see links at the end of the post). This post is just a sum up of what worked in my case (in case I need to redo it). I strongly suggest to check the links at the end of the article.

The solution rely on 2 software:

  • hostapd
    HostAPD is a user space daemon for access point and authentication servers. That means it can will turn your Raspberry Pi into an access point that other computers can connect to. It will also handle security such that you can setup a WiFi password.
  • isc-dhcp-server
    isc-dhcp-server is the Internet Systems Consortium’s implementation of a DHCP server. A DHCP server is responsible for assigning addresses to computers and devices connection to the WiFi access point.
    Some people use udhcpd which is lighter version

The first thing to do is install the software :

sudo apt-get update
sudo apt-get install isc-dhcp-server hostapd

DHCP configuration

Then configure the DHCP server with 2 files :

  • /etc/default/isc-dhcp-server
#This will make the DHCP server hand out network addresses on the wireless interface
Change “INTERFACES=""” to “INTERFACES="wlan0"”
  • /etc/dhcp/dhcpd.conf

comment the following lines :

option domain-name "example.org";
option domain-name-servers ns1.example.org, ns2.example.org;

make the DHCP as master on the domain by removing the comment at lines

#authoritative;

define a network and dhcp config by adding the following block (This configuration will use the Google DNS servers at 8.8.8.8 and 8.8.4.4. )

subnet 192.168.10.0 netmask 255.255.255.0 {
range 192.168.10.10 192.168.10.20;
option broadcast-address 192.168.10.255;
option routers 192.168.10.1;
default-lease-time 600;
max-lease-time 7200;
option domain-name "local-network";
option domain-name-servers 8.8.8.8, 8.8.4.4;
}

Network interface

Now that the DHCP server is configured we will setup the network card (wifi dongle in our case) with static IP

edit the file :

/etc/network/interfaces

remove everything related to “wlan0” and past :

allow-hotplug wlan0

iface wlan0 inet static
address 192.168.10.1
netmask 255.255.255.0

and now the last configuration step is the hostapd server

HostApd

create new file:

/etc/hostapd/hostapd.conf

past :

interface=wlan0
driver=nl80211
#driver=rtl871xdrv
ssid=MyPi
hw_mode=g
channel=6
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=raspberry
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

Be aware of the driver choice : nl8021.

Then the last file to configure :

/etc/default/hostapd

Find the line #DAEMON_CONF=”” and edit it so it says DAEMON_CONF=”/etc/hostapd/hostapd.conf”

Don’t forget to remove the # in front to activate it!

Then you can test with :

sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf

If it does not works with an error related to the driver….you need to DL the one made by adafruit (see llinks at the end)

Extra

To start the 2 services :

sudo service isc-dhcp-server start
sudo service hostapd-server start

and if you want to start them at boot time :

sudo update-rc.d isc-dhcp-server enable
sudo update-rc.d hostapd enable

Useful links found in my research:

Broadcast Raspberry Pi camera

I need to broadcast the stream of my Raspberry pi camera mounted in front of the train. More info on the “train” project here (part1) and here TODO

PHOTO TODO

This is the results of my search on the possible solutions :

motion

more for security or motion detection

with VLC

The camera stream is send to vlc which forward it over the network

raspivid -o - -t 0 -hf -w 640 -h 360 -fps 25 | cvlc -vvv stream:///dev/stdin --sout '#rtp{sdp=rtsp://:8554}' :demux=h264

-Slow, Delay

+Easy

Direct capture with the new recent v4l2 driver

cvlc v4l2:///dev/video0 --v4l2-width 1920 --v4l2-height 1080 --v4l2-chroma h264 --sout '#standard{access=http,mux=ts,dst=0.0.0.0:12345}'

+Easy

-Require VLC

with ffmpeg//ffserver

https://www.ffmpeg.org/

A complete, cross-platform solution to record, convert and stream audio and video.

–The stream is capture and stream by ffmpeg

raspivid -n -vf -hf -t 0 -w 960 -h 540 -fps 25 -b 500000 -o - | ffmpeg -i - -vcodec copy -an -metadata title="Streaming from raspberry pi camera" -f flv $RTMP_URL/$STREAM_KEY

with MJPG streamer

MJPG-streamer takes JPGs from Linux-UVC compatible webcams, file system or other input plugins and streams them as M-JPEG via HTTP to web browsers

http://sourceforge.net/projects/mjpg-streamer/

with gstreamer

GStreamer is a library for constructing graphs of media-handling components. The applications it supports range from simple Ogg/Vorbis playback, audio/video streaming to complex audio (mixing) and video (non-linear editing) processing.

http://gstreamer.freedesktop.org/

RPi caminterface

RaspiMJPEG is an OpenMAX-Application based on the mmal-library, which is comparable to RaspiVid. Both applications save the recording formated as H264 into a file

http://elinux.org/RPi-Cam-Web-Interface

WebRTC UV4L

WebRTC is a very powerful standard, modern protocol and gives a number of nicefeatures

http://www.linux-projects.org/modules/news/article.php?storyid=174

-only works with pi2

picamera

The project consists primarily of a class (PiCamera) which is a re-implementation of high-level bits of the raspistill and raspivid commands using the ctypes based libmmal header conversion, plus a set of encoder classes which re-implement the encoder callback configuration in the aforementioned binaries. Various classes for specialized applications also exist (PiCameraCircularIO, PiBayerArray, etc.)

https://picamera.readthedocs.org/en/release-1.10/install2.html

avconv

avconv is a very fast video and audio converter that can also grab from a live audio/video source. It can also convert between arbitrary sample rates and resize video on the fly with a high quality polyphase filter.

CRTMPServer

http://www.rtmpd.com/

crtmpserver it is a high performance streaming server able to stream (live or recorded)

live555

http://www.live555.com/liveMedia/

Not tested

PiStreaming

https://github.com/waveform80/pistreaming

Not tested


Finally I decided to use “RPi caminterface” which has the best feedback. I confirms it works out of the box (which save me lot of times).
I could maybe migrate to “WebRTC UV4L” if I decide to go to a Pi2 in the future…


 

Here are the links I find during my search :

Bluetooth Low Energy device and Android communication

Long time I didn’t post an article since I was busy with my move to Boston…..

I was so tired of having to type my Android Password all the time I wanted to use my phone (when listening to music for example) that I decided to do something about it….. Nevertheless I didn’t want to remove the password protection on my phone since it contains lot of important information.

First I decided to have a look on NFC communication to be able to unlock the phone with a NFC card. I didn’t have lot of success with this lead since the NFC module is stop when the device is locked (as far as I understand).

Then I thought about using Bluetooth communication since I already had some experience on BT communication under android (link). I also wanted to have a look on Bluetooth last version “Bluetooth low energy”. It seems a promising technology (Apple Ibeacon, Smartwatch, Activity tracker…). I finally decided to create a service on Android which will detect the BLE devices in range and depending on that can remove/reset the android security policy. Basically if my BLE device is in range the service will remove the android security policy so the phone will no longer require a password. Moreover as soon as the BLE device is no longer in range the service will revert to the previous security policy (see video for concrete example).

I didn’t focus too much on the hardware part which is simply composed of a BLE beacon. To do it I simply used a Arduino Leonardo and a BLE Arduino shield: http://redbearlab.com/bleshield/

BLE_Ardu

The Arduino code is the example provided in the shield library available here

The Android part of the project is composed of 2 parts: BLE interface and Android Device Policy interface.

BLE interface

The first important thing to understand is that the support of BLE is only working fine with Android > 4.4 (the official doc mentioned 4.3 but some people report issue when trying to use 4.3 and BLE). Be sure to use the API >= 4.4.

There is pretty good tutorial on Google Android Website available here : https://developer.android.com/guide/topics/connectivity/bluetooth-le.html

I mainly follow it (with lot of simplification to kept the only necessary step) to dialogue with my BLE device. It would be useless to describe it here but the process is pretty straightforward :

  • Declare valid permission (some website indicate that the BLUETOOTH_ADMIN is only necessary to turn on/off the BT and thus you don’t need it if the BT is already ON….this is correct for BT but not for BLE. )
  • Activate BT if necessary. Similar to the BT process
  • Scan for BLE devices : Don t forget to stop scanning ASAP otherwise it will empty your phone battery. Implement the scan callback (called every time that the scan finds a device
  • Connect to the BLE : BLE connection is different from the usual BT. There is more granularity in the association process due to the fact that the BLE device can expose several different services with different access level. For example the device could let you access public information without any access check and offer private functionality (like administration) with user access control.
  • Register to BLE change : Once connected we also reegister to the BLE device status changes. This will be used by the process to activate (or not) the Android security policy. This is done by implementing the callback “onConnectionStateChange”
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                Log.i("MyActivity", "onConnectionStateChange");
                gatt.readRemoteRssi();
                if(newState ==  BluetoothProfile.STATE_CONNECTED) {
                    aDeviceInRange = true;
                    deactivate_lock();
                    Log.i("MyActivity", "Device is in range");
                }
                else {
                    aDeviceInRange = false;
                    Log.i("MyActivity", "Device is not in range");
                    activate_lock();
                }
    
                runOnUiThread(new Runnable() {
    
                    @Override
                    public void run() {
                        Log.i("MyActivity", "scanning");
    
                        TextView t = (TextView)findViewById(R.id.textView4);
                        t.setText("Status : " + String.valueOf(aDeviceInRange));
                    }
                });
            }
    

 Android Device Policy changes

Unlike the BLE connection there is no clear documentation about “how to change android security setting”. If you look for it you will find 2 things : KeyguardManager/KeyguardLock and WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD.

So let’s be clear …. There is no way to do it with the “layout flag”. The best you will achieve is to be able to turn on the phone and display your application but you will not be able to exit your application. If you try to exit your application the OS will ask for the password. That is the best you can do today with this solution.

The other one “KeyguardManager/KeyguardLock” could (or could not) work depending on your luck ! Indeed it has been deprecated since API 13 as explained on the official documentation here : http://developer.android.com/reference/android/app/KeyguardManager.KeyguardLock.html

Hopefully it works fine in my case so I didn’t dig too much for another solution but if it doesn’t works for you I suggest to check the android device administration class available here (but continue reading) : http://developer.android.com/guide/topics/admin/device-admin.html

The lock/unlock code is thus pretty simple with the 2 following functions :

    public void activate_lock() {
        Log.i("MyActivity", "click on activate lock button");
        boolean isAdmin = mDevicePolicyManager.isAdminActive(mComponentName);
        if (isAdmin) {
            boolean result = mDevicePolicyManager.resetPassword("test",DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY);
            KeyguardManager kgManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
            KeyguardManager.KeyguardLock lock = kgManager.newKeyguardLock(Context.KEYGUARD_SERVICE);
            lock.reenableKeyguard();
        }else{
            Toast.makeText(getApplicationContext(), "Not Registered as admin", Toast.LENGTH_SHORT).show();
        }
    }

    public void deactivate_lock() {
        Log.i("MyActivity", "click on remove lock button");
        boolean isAdmin = mDevicePolicyManager.isAdminActive(mComponentName);
        if (isAdmin) {
            mDevicePolicyManager.resetPassword("",0);
            KeyguardManager kgManager = (KeyguardManager)getSystemService(Activity.KEYGUARD_SERVICE);
            KeyguardManager.KeyguardLock lock = kgManager.newKeyguardLock(Context.KEYGUARD_SERVICE);
            lock.disableKeyguard();
        }else{
            Toast.makeText(getApplicationContext(), "Not Registered as admin", Toast.LENGTH_SHORT).show();
        }
    }

The full code (not sure it include the last changes done just before I move to Boston) available on my BitBucket account here and a demo video is available on youtube here.

Next steps

None ! indeed I just read an article about android 5.0 and this exact functionality has been integrated on the OS itself so my app is no longer useful. The full article is available on TC : http://techcrunch.com/2014/10/28/android-5-lollipop-security-features/ but it solve the exact same problem as you can see from the abstract below :

Lollipop adds some new lock methods that make it easier to keep your 
device secure, which is a huge boon to the overall integrity of the 
platform. The biggest roadblock to mobile device security is actually 
user apathy, which sees people skipping basic security practices like 
implementing a lock screen pin code because it’s inconvenient when 
you’re checking your device every few minutes. Lollipop offers Smart 
Lock to help address this, which uses paired devices to let you tell 
your device it’s okay to open up without requiring a password or 
other means of authentication.

Android Studio 0.8.14 – missing SKD

I just had a new PC so I needed to reinstall Android Studio to do some Android DEV. I already install it several time previously but face an issue in the last version (0.8.14) available on the official website : https://developer.android.com/sdk/installing/studio.html

The download link mentioned that the SDK is part of the download package:

Androidpackage

The install page also details the procedure :

installAndroidStudio

Both of these 2 sources lead to think that the SDK is part of the installer…which in no longer the case since 0.8.14. So if you try to follow this procedure Android studio will not start properly (it will ask you for the SDK). I thought there was something wrong with my install and lost too much time investigating what could be wrong. I tried to run it as admin or other trick found on SO…..this is completely useless !

If you have the same error it is in fact completely normal ! Since 0.8.14 the SDK is no longer part of the DL and you have to install it yourself. The documentation is not up to date which is very confusing but the information is available on some place but hard to find. You will have it on the “recent change” page on the beta side channel available here : http://tools.android.com/recent/androidstudio0814inbetachannel

AndroidNoSdk

So in case you have the same issue…..don’t spend time on useless investigation and just install the SDK yourself ! I hope it will help people until google update the info on the official install doc.

 

Root ssh is never possible with CentOs/RHEL

I spend 1 day to understand why I was not able to log with root user on GCE for RH and CentOs image whereas it works fine for Debian image. I post here the results of my findings hoping it will save time for some other people (I also open a bug report : https://code.google.com/p/google-compute-engine/issues/detail?id=114)

For my application I wanted to be able to connect to my new CentOs VM with root user. I don’t want to go in the “allow ssh with root is dangerous”….

I made all the necessary changes on the SSH conf on the new created centOs image but I was not able to log on the VM. I know that the setup was correct since I do the exact same scenario with a debian image and it was working just fine….Thus I start suspecting there was an issue….

I start investigate and found out that there are some google scripts running on background on each VMs to take care of replicating the SSH keys defined on GCE console to the VMs. The scripts are available here :

https://github.com/GoogleCloudPlatform/compute-image-packages

I added some logs and see the following pattern:

[AuthorizeSshKeys] user : charles ssh_keys : ['ssh-dss ….vQBN7nAVg== charles@ip-172-31-45-251'] UID : 500
[WriteAuthorizedSshKeysFile] Original File : /root/.ssh/authorized_keys
[WriteAuthorizedSshKeysFile] New_keys_path : /tmp/tmpjwGRv8
[WriteAuthorizedSshKeysFile] UID : 0 GID : 0
[AuthorizeSshKeys] user : root ssh_keys : ['ssh-dss …..nC4RvQBN7nAVg== root@ip-172-31-45-251'] UID : 0
[WriteAuthorizedSshKeysFile] Original File : /root/.ssh/authorized_keys
[WriteAuthorizedSshKeysFile] New_keys_path : /tmp/tmp15enQW
[WriteAuthorizedSshKeysFile] UID : 11 GID : 0
[AuthorizeSshKeys] user : operator ssh_keys : [] UID : 11
[WriteAuthorizedSshKeysFile] Original File : /home/charles/.ssh/authorized_keys
[WriteAuthorizedSshKeysFile] New_keys_path : /tmp/tmpDB6knL
[WriteAuthorizedSshKeysFile] UID : 500 GID : 500

The script update the ssh key for the following users : Charles, root, and then “operator”. I understand the 2 firsts users “Charles” and “root” which are the users I defined in GCE console nevertheless the user “operator” is more strange especially because it end up by changing the “root” sshkey.

I investigate deeper the python code and understand this last flow updating “operator” user. The google python daemon use /etc/passwd to determine the path to the ssh key and on RedHat (or Centos) the operator user is defined with :

User UID GID Home Directory Shell
root 0 0 /root /bin/bash
operator 11 0 /root /sbin/nologin

(source : https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/3/html/Reference_Guide/s1-users-groups-standard-users.html)

The « home dir » of « operator » is thus /root…..leading the daemon to update /root/.ssh/auth… when working on “operator” user. It thus removes the real “root” file preventing the root login. Checking deeper this flow is designed to clean the “ssh key” file for the users which are not present on the GCE console (which is the case for “operator”).

I would like to have more time to propose a patch but I me late on my project. I done a workaround which is to create a new centOs image with /sbin as the home dir for the operator user :

usermod -m -d /sbin operator

and then everything works fine !

For the final solution I would suggest to change the script to maybe check if a “home” is shared and do nothing in this case or change the RH image.

Update (Nov2014) : The issue has been fixed on GCE side with last version of images.

BT discovery on Android

This article present how to use Bluetooth on Android device. The full project include Arduino Leonardo card and is detailed on this article : http://djynet.net/?p=639

First….some ressources to understand BT communication and BT handling on Android :

  • https://learn.sparkfun.com/tutorials/using-the-bluesmirf/all
  • https://learn.sparkfun.com/tutorials/bluetooth-basics/all
  • http://developer.android.com/guide/topics/connectivity/bluetooth.html

Before starting….I thanks the guy who wrote the following article which help me a lot to understand android – Arduino BT links :
http://english.cxem.net/arduino/arduino5.php

I finish the DEV but it happen to be more complicated than I originaly think it would be… Especialy the “receive” part from Android which require ansynch tasks. Nevertheless I put lot of comments in the code so it should be easy to understand it.

The first things is to request BT use in the manifest :

<uses-permission android:name=”android.permission.BLUETOOTH” />

Then I created a simple layout with some button and textview to interact with the user

BT_Moisture_interface

The first section hold the potential BT devices and allow to connect to the one selected. The second section is only 1 button “Moisture request” which will send the char ‘h’ to the arduino board. Last text view is used to display the Arduino response which is the moisture value in the earth.

The association button-callback is done in the xml view directly :

<Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/connect"
        android:onClick="myClickHandler"
        android:text="@string/hello_world" />

At startup the program check if the phone as BT capability :

if (mBluetoothAdapter == null) {
            // Device does not support Bluetooth
            Log.w("MyActivity", "Device does not support Bluetooth");
            Toast.makeText(this.getParent(), "Go buy a more recent phone", Toast.LENGTH_LONG).show();
        }
and if the BT is not turn on it will request it to the OS (which will prompt the user) :
if (!mBluetoothAdapter.isEnabled()) {
                Log.i("MyActivity", "BT is not enabled. I request to start it");
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, 643);
            }

Another solution is to turn it on without asking kindly but it request more permission (in manifest).

Once the BT is ready the program will populate the UI with the list of paired devices :

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
        // If there are paired devices
        if (pairedDevices.size() > 0) {

            //Fill the spinner on view with devices
            Spinner spinner = (Spinner) findViewById(R.id.spinner);
            // Create an empty ArrayAdapter
            ArrayAdapter <CharSequence> adapter = new ArrayAdapter <CharSequence> (this, android.R.layout.simple_spinner_item );
            // Specify the layout to use when the list of choices appears
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            // Apply the adapter to the spinner
            spinner.setAdapter(adapter);
            //Populate IT !!
            for (BluetoothDevice device : pairedDevices) {
                adapter.add(device.getName() + "\n" + device.getAddress());
            }
        }

I didn’t handle the BT discovery here….which means that I already paired my Arduino with my phone. This operation could be done directly in android when you turn on the BT. It need to be done only 1 time and will ask you the code of the arduino BT module (1234).

Then….the user can select its module in the drop down menu (that we just populate in the previous function) and open a connection with it by pressing the “connect” button. It will call button callback :

public void myClickHandler(View v) {
        Log.i("MyActivity", "click button");
        connectMoisture();
    }

which call the real interesting process 🙂

protected void connectMoisture()
    {
        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        Log.i("MyActivity", "We open the connection");
        // I will use the standard SPP UUID - remember it is not link to our device on contrary of MAC address
        UUID aSppUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
        // The Arduino BT receiver address
        String aArduinoBtAddress = "00:06:66:60:42:BE";
        try{
            Log.i("MyActivity", "Going to retrieve the device");
            BluetoothDevice aBtDevice = mBluetoothAdapter.getRemoteDevice(aArduinoBtAddress);
            Log.i("MyActivity", "Device retrieved, creating socket now");
            _blueToothSocket = aBtDevice.createRfcommSocketToServiceRecord(aSppUuid);
            Log.i("MyActivity", "Socket created");
        }catch(IOException createSocketException){
            Log.e("MyActivity", "error1508"+ createSocketException.getMessage());
        }
        // Establish the connection.  This will block until it connects.
        Log.i("MyActivity", "Will try to connect to remote device");
        try {
            _blueToothSocket.connect();
            Log.i("MyActivity", "Connection is done");
        } catch (IOException e) {
            Log.e("MyActivity", "error148"+ e.getMessage());
            try {
                Log.i("MyActivity", "Closing socket");
                _blueToothSocket.close();
                Log.i("MyActivity", "Socket closed");
            } catch (IOException e2) {
                Log.e("MyActivity", "another issue" + e2.getMessage());
            }
        }
        // Step 3 create stream to talk with BT deice
        try {
            _streamOutgoing = _blueToothSocket.getOutputStream();
        } catch (IOException e) {
            Log.e("MyActivity", "another issue" + e.getMessage());
        }
    }
Now the program is connected to the device (the Ardunio BT board will probably have a LED which will reflect this new state). The user can now request the moisture value by clicking on the second button :
public void mySecondClickHandler(View v) {
        Log.i("MyActivity", "Sending h");
        //sendData("l");
        sendData("h");

    }

which call a sending routing with ‘h’ char :

protected void sendData(String message) {
        // start thread which handle input BT data before we send the request to Arduino.
        // With this design we know that we will be able to handle response
        ImplementsRunnable rc = new ImplementsRunnable();
        Thread t1 = new Thread(rc);
        t1.start();
        // The thread which is listening to input data from Arduino is now started
        // We can go to next step and send request to Arduino

        //Convert the String to send to byte
        byte[] msgBuffer = message.getBytes();
        Log.d("MyActivity", "About to send : " + message);

        try {
            _streamOutgoing.write(msgBuffer);
            //The next line is sending h char. I kept it as a debug test because I was worried Android will add extra char which will not be understand on Arduino side like end of line
            //_streamOutgoing.write('h');
        } catch (IOException e) {
            Log.e("MyActivity", "Error when trying to send data : " + e.getMessage());
        }
        //This is over. The Arduino response will be handle separately by another thread that we started before sending the request
    }

OK….So here I have to explain the first part where we start a dedicated thread. Before sending the request to Arduino Board we start a thread which will wait for incoming data on BT. It is the normal way to handle incoming message. The other part of the function is the data sending to arduino.

After this call the arduino received the char ‘h’ which trig a moisture detection and it will send back the moisture value to the BT module which will send it to the Android Phone.

As explained the reception is done in a dedicated thread. This is done by the following class which implement the “runable” interface :

class ImplementsRunnable implements Runnable {
        private InputStream _streamIncoming = null;

        public void run() {
            Log.d("MyActivity", "Thread run");

            //First we retrieve the input stream of the BT socket to be able to read incoming bytes
            try {
                _streamIncoming = _blueToothSocket.getInputStream();
                Log.i("MyActivity", "Input stream acquired");
            } catch (IOException e) {
                Log.e("MyActivity", "another issue" + e.getMessage());
            }

            //This single read works because I only wait for one message from Arduino but we should have a infinite loop here to catch everything arriving all the time
            try {
                //Not clean but we only receive a small message
                BufferedReader aMyBufferReader = new BufferedReader(new InputStreamReader(_streamIncoming));
                String aArduinoDataStr = "";
                aArduinoDataStr = aMyBufferReader.readLine();

                Log.i("MyActivity", "Received " + aArduinoDataStr );
                _ThreadMsgHandler.obtainMessage(31444, aArduinoDataStr).sendToTarget();     // Send to message queue Handler

            } catch (IOException e) {
                Log.e("MyActivity", "another issue" + e.getMessage());
            }
            Log.i("MyActivity", "Leaving thread run method " );
        }
    }

Once data are received by this thread they will be forwarded to the UI thread. This is done by the use of ‘Android handler’ in the UI thread :

_ThreadMsgHandler = new Handler(Looper.getMainLooper()) {
            //Will be called when new message arrive from other threads
            public void handleMessage(Message msg) {
                Log.d("MyActivity", "Handler is handling a message of type : " + msg.what);
                switch (msg.what) {
                    //Random ID .... should be the same as the one use when sending the msg from the thread
                    case 31444:
                        String aMyMoistureValue = (String) msg.obj;
                        // For now we only log it and toast it
                        Log.i("MyActivity", "Toasting moisture value : " + aMyMoistureValue);
                        Toast.makeText(MyActivity.this, aMyMoistureValue, Toast.LENGTH_LONG).show();
                        TextView aMyTextViewHandlingResponse = (TextView) findViewById(R.id.textView);
                        aMyTextViewHandlingResponse.setText("Moisture: " + aMyMoistureValue);
                        break;
                    //I think it should never occurs but just to be safe we log it
                    default:
                        Log.w("MyActivity", "Received an unknown message type : " + msg.what);
                }
            };
        };

Don’t forget…..this methods in on the UI thread ! We will come back to it after I finish explaining my runable class…..

The Data are send from the runable class to the UI thread with the handler :

_ThreadMsgHandler.obtainMessage(31444, aArduinoDataStr).sendToTarget();     // Send to message queue Handler

which is “catch” in the UI thread by the handler I just show before. The important point is the 31444 which has to be the same and act as an unique identifier. To finish the UI thread toast this value (debuging) and update the textview.

The results with the sensor in moist earth (or not) with the Arduino and Android output.

Moisture_Ardu

Andro_Moisture

The whole code for the project (Android and Arduino) is on my bitbucket account here.

 

 

Android 0.8 Beta – INSTALL_FAILED_OLDER_SDK

I updated my android studio to the last version 0.8.2. Since this update it is no longer possible to have my APP runing on my phone.

Everytime I tried to upload it to the phone I have the following error :
INSTALL_FAILED_OLDER_SDK

I tried a fresh install too leading to the same issue. After some googling it seems the issue impact lot of people :

  • http://stackoverflow.com/questions/24465289/android-studio-failure-install-failed-older-sdk
  • http://stackoverflow.com/questions/24469754/failure-install-failed-older-sdk-in-android-studio
  • https://code.google.com/p/android/issues/detail?id=72840
  • http://blog.csdn.net/hotlinhao/article/details/37498201
  • ….

I m not interested in the last API of Android L since my phone is only 4.3 nevertheless even by specifiying that I want to be using 4.3 the build didn’t take it into account. The solution I found is to remove all Android L SDK/Compiler from  the SDK manager and install android 4.3 (and/or 4.4)

Android4-3bug

and then restart android. After that the SDK selection will works fine and if you create a new project you should have the following gradle file.

gradleXml

Now the upload to the phone works fine 😉

Google plus sing-in API

Maintenant que je connais les bases de Flask je peux continuer mon test de l’API Google Plus.

La documentation la plus a jour est disponible ICI : https://developers.google.com/+/ et je vous conseil aussi de jeter un œil au tutorial disponible ICI : http://www.googleplusdaily.com/2013/03/add-google-sign-in-in-6-easy-steps.html

J’ai réalisé un site web minimaliste en utilisant Jquery Mobile et Flask. Le site offre la possibilité de se logger avec son compte Google grâce a la méthode de sign in de Google plus.

Création du client ID

Pour pouvoir utiliser les services de google il faut déclarer notre projet dans la console disponible a l’adresse suivante :

https://console.developers.google.com/project

Il faut ensuite créer un nouveau projet (ou utiliser un de vos projets existants). Il faut ensuite activer l API Google + pour ce projet en cliquant sur API.

GoogleApiOn

Il faut enfin créer une clé d’identification pour utiliser l’API. Pour cela on clique sur le sous menu “credentials” situe en dessous du menu API.

GoogleApiCle

 Site web

Le site est très simple et repose sur l’utilisation de Flask (voir mon article précédant). L’utilisation de l’API google est assez bien documente (voir liens au début de l’article) et je ne vais pas répéter toutes les étapes.

L’ensemble du code est disponible sur bitbucket ICI :
https://bitbucket.org/charly37/googlesign/overview

Il suffit de remplacer le client ID présent dans le code par celui crée dans l’étape précédente :

class="g-signin"
data-callback="signinCallback"
data-clientid="67694002414-idd640ukscsntd4nmn80gg66i6sirup1.apps.googleusercontent.com"
data-cookiepolicy="single_host_origin"
data-requestvisibleactions="http://schemas.google.com/AddActivity"
data-scope="https://www.googleapis.com/auth/plus.login">

Le résultat :

GoogleSignInApiLogin

A la fin du logging le site affichera le nom de l’utilisateur :

GoogleApiResult

Voila 😉