Wednesday, June 19, 2013

Installing ejabberd2 on CentOS and configure a virtual host on Apache2

1. Enable epel yum repository

Centos 5.x
wget http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
sudo rpm -Uvh epel-release-5*.rpm

Centos 6.x
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
sudo rpm -Uvh epel-release-6*.rpm

2. Install ejabberd2
yum --enablerepo=epel install ejabberd

3. Start the ejabberd2 service
service ejabberd start

4. Edit the virtual hosts configuration file and add
  ProxyPass /http-bind  http://127.0.0.1:5280/http-bind/
  ProxyPassReverse  /http-bind   http://127.0.0.1:5280/http-bind/
  Header set Access-Control-Allow-Origin "YOUR_VIRTUAL_SERVER_HOSTNAME"

(please note that using "Header set Access-Control-Allow-Origin" enables Cross-origin resource sharing and using a wildcard as origin should not normally be used)

This is generally not appropriate. The only case where this is appropriate is when a page or api response is considered completely public content and it is intended to be accessible to browsable to everyone. Including any code on any site.
(http://en.wikipedia.org/wiki/Cross-origin_resource_sharing)

5. Test configuration
service httpd configtest

6. Reload apache configuration
service httpd reload

Since ejabberd comes with http-bind enabled out of the box
 
{5280, ejabberd_http, [
 %%{request_handlers,
 %% [
 %%  {["pub", "archive"], mod_http_fileserver}
 %% ]},
 captcha,
 http_bind,
 http_poll,
 %%register,
 web_admin
]}

you should now be able to access the XMPP over BOSH (XEP-0206) server in your browser looking somewhat like below.


 

Monday, June 03, 2013

Xamarin Mono.Droid Receiving different bluetooth devices data records

When you are working with several different Bluetooth devices (from different manufacturers) you will have to be able to handle different types of data records. The official Android Bluetooth sample ported for Xamarin/Mono.Droid can be found at BluetoothChatService.cs. This was the code I used for inspiration when I built this app.
I could however not really get the code to work as I wanted and the problem was located in the following method Run().
public override void Run ()
{
 Log.Info (TAG, "BEGIN mConnectedThread");
 byte[] buffer = new byte[1024];
 int bytes;

 // Keep listening to the InputStream while connected
 while (true) {
  try {
   // Read from the InputStream
   bytes = mmInStream.Read (buffer, 0, buffer.Length);

   // Send the obtained bytes to the UI Activity
   _handler.ObtainMessage (BluetoothChat.MESSAGE_READ, bytes, -1, buffer)
    .SendToTarget ();
  } catch (Java.IO.IOException e) {
   Log.Error (TAG, "disconnected", e);
   _service.ConnectionLost ();
   break;
  }
 }
}
The problem is the following call
// Send the obtained bytes to the UI Activity
_handler.ObtainMessage (BluetoothChat.MESSAGE_READ, bytes, -1, buffer).SendToTarget ();
which might not always send back the entire device record to the handler. This is caused by the various devices implementation of how to send the data record back as a byte stream to the mobile device/phone might not finish, before the while loop is starting another iteration, as well as the multithreading and the context switches that occurs in the BluetoothChatService.

What I discovered while testing was that for some devices it was working out of the box with the default code in the Run method above. However on some more complex devices which were sending larger data records back, it never seemed to work.

After spending some time analyzing the problem - being new to the bluetooth scene and Mono.Droid development - I found that data records got chopped into pieces in the while(true) loop in the above Run() method. Assuming that a full data record was 65 bytes, sometimes the code would pass 13 bytes to the SendToTarget() method. The next iteration might yield 31 bytes and the last 21 bytes was yielded on the 3rd pass. 

The number of bytes returned on each iteration was never the same and there was no specific pattern to this. To be able to handle this for different devices sending data in different ways I needed some kind of smart buffering. I came up with the following.
public override void Run ()
{
 Log.Info (TAG, "BEGIN mConnectedThread");
 byte[] buffer = new byte[1024];
 int bytes;
 
 // Keep listening to the InputStream while connected
 while (true) {
  try {
   // Read from the InputStream
   bytes = mmInStream.Read(buffer, 0, buffer.Length);

   var messagePart = new byte[bytes];
   Array.Copy(buffer,messagePart, bytes);

   // Send the obtained bytes to the UI Activity
   _handler.ObtainMessage(MESSAGE_READ, bytes, -1, messagePart)
    .SendToTarget();
  } catch (Java.IO.IOException e) {
   Log.Error (TAG, "disconnected", e);
   _service.ConnectionLost ();
   break;
  }
 }
}
The new code is only a little bit different in that I am no longer sending back the buffer but instead only the partial message (messagePart).

In the handler that handles the read bytes I changed the implementation from what can be found here BluetoothChat.cs.
case MESSAGE_READ:
 byte[] readBuf = (byte[])msg.Obj;
 // construct a string from the valid bytes in the buffer
 var readMessage = new Java.Lang.String (readBuf, 0, msg.Arg1);
 bluetoothChat.conversationArrayAdapter.Add (bluetoothChat.connectedDeviceName + ":  " + readMessage);
 break;
to the following code

case BluetoothService.MESSAGE_READ:
 byte[] readBuf = (byte[])msg.Obj;
 ParseBluetoothDeviceReading(readBuf);
 break;
and the ParseBluetoothDeviceReading() method looking like this
public void ParseBluetoothDeviceReading (byte[] readBuffer)
{
 if (readBuffer == null || readBuffer.Length <= 0)
  return;

 var deviceRecord = _zephyrResponseParser.ParseDeviceResponse(readBuffer);
 _data.LungFunction= deviceRecord.LungFunction;
 lblValue.Text = deviceRecord.LungFunction.ToString("0.00");
}
the data record buffer is implemented in the _zephyrResponseParser which is of type IDeviceResponseParser. The interface IDeviceResponseParser looks like the following

public interface IDeviceResponseParser<TDataRecord>
{
 TDataRecord ParseDeviceResponse(byte[] response);
}
and finally the actual device specific data record parser for the zephyr device.

using System.Collections.Generic;

namespace Droid.Devices.Zephyr
{
 public class ZephyrResponseParser : IDeviceResponseParser<ZephyrRecord>
 {
  public const int DeviceMessageLength = 65;
  
  private List<byte> _messageBuffer = new List<byte>();

  public ZephyrRecord ParseDeviceResponse(byte[] response)
  {
   // Since the data (byte[]) that we are getting is retreived from a BluetoothNetworkStream there are no guarantees that we will get the full message in one go.
   // For that reason we need to buffer it our selves until whe have a full message
   _messageBuffer.AddRange(response);
   if (_messageBuffer.Count < DeviceMessageLength)
   {
    // Not full message return
    return new ZephyrRecord();
   }

   // Full message, pass on to temp so we can reset the local messageBuffer for the next
   // device message
   var temp = _messageBuffer.ToArray();

   // Reset buffer
   _messageBuffer.Clear();
   
   // Now process the full message
   response = temp;
   if (response.Length >= DeviceMessageLength)
   {
    var deviceRecord = ExtractDataFromRawByteStream();
    return new ZephyrRecord { LungFunction = deviceRecord.LungFunction };
   }
   return new ZephyrRecord();
  }
 }

 ...
 
 public class ZephyrRecord
 {
  public float LungFunction { get; set; }
 }
}
This has proven to work so far, without any known problems, for several different devices that are working very differently, has different manufacturers and are measuring different medical parameters.

Sunday, June 02, 2013

Android 4.0.3 and 4.0.4 bluetooth pairing needed on every connection

While developing a cross mobile device app using Xamarin, I ran into a strange problem. Behind the cross device abstraction, that was utilized in both the Android and the iOS version of the app, the Android specific code had a problem. The problem manifested it self on one Samsung Galaxy 10.1 tablet running 4.0.3, as well as one running 4.0.4. The problem was not present on the reference "lowest common denominator tablet" (this was also a Samsung Galaxy 10.1 tablet, just running Android 3.2).

After some Google searches and not really coming up with anything specific, I found this link which was actually showing me the solution, although I did not know it at the time.

Android Programmatically Bluetooth Pairing

Our app is using a somewhat modified version of the official Android Bluetooth sample ported to monodroid, it can be found here BluetoothChat.

The problem showed out to be this line "tmp = device.CreateRfcommSocketToServiceRecord (MY_UUID);"

changing this to 

tmp = device.CreateInsecureRfcommSocketToServiceRecord (MY_UUID);

solved the problem for 3 different devices for me.

Some more Googling gave me the apparent reason behind this. There seems to be a bug in Android 4.0.3 and 4.0.4+ that is causing the Bluetooth pairing to be forgotten.

This is documented amongst others on Bluetooth connection on Android ICS not possible.

I spent quite some time trying to figure out what was wrong with the code, being in the mindset "I must be doing something wrong" and being a bit reluctant to start the "blamegame".

I hope this might help someone else out there.

Below are a few links that I went through in my hunt for a solution, they are all one way or another corroborating my findings.

ICS can't pair BT devices without PIN 
Bluetooth RFCOMM Server Socket no longer connects properly to embedded device on ICS 4.0.3