Undetected USB accessory with Arduino Due connected to Android MiniPad (MPgio) - android

I have problem working on an Android accessory job with Arduino Due which is uploaded Blink.ino (other samples too). The problem is that I couldn't detect any USB accessory (or List) from UsbManager got from getSystemService("USB_SERVICE") in any case with attaching or detaching.
My code is below.
1. manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.signalhello"
android:versionCode="1"
android:versionName="1.0" >
<!-- <uses-feature android:name="android.hardware.usb.accessory" />
<uses-feature android:name="android.hardware.usb.host" /> -->
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.example.signalhello.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED" />
<action android:name="android.hardware.usb.action.USB_ACCESSORY_DETACHED" />
</intent-filter>
<meta-data
android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
android:resource="#xml/accessory_filter" />
</activity>
</application>
</manifest>
2. accessory-filter.xml in res/xml/
<?xml version="1.0" encoding="utf-8"?>
<resources>
<usb-accessory manufacturer="Arduino-er"/> // I tried other options like <usb- accessory vendor-id="9025" product-id="62"/>
<usb-device vendor-id="9025" product-id="62"/>
<usb-accessory vendor-id="2341" product-id="003e"/>
<usb-device vendor-id="2341" product-id="003e"/>
</resources>
3. MainActivity
package com.example.signalhello;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class MainActivity extends Activity {
private static final String ACTION_USB_PERMISSION =
"net.hardroid.adk.example.action.USB_PERMISSION";
private PendingIntent mPermissionIntent;
private boolean mPermissionRequestPending;
// USB가 감지되었을 때의 이벤트를 받음.
private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("onReceive", "action: " + action);
tv01.setText("action: " + action);
if (ACTION_USB_PERMISSION.equals(action)) {
// 사용자에게 Android Accessory Protocol을 구현한 장비가 연결되면
// 수락할 것인지 문의한 다이얼로그에 대한 사용자의 선택 결과를 받는다.
synchronized (this) {
Log.d("onReceive", "Getting UsbAccessory...");
UsbAccessory accessory = intent
.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
Log.d("onReceive", "Accessory is null ? " + (accessory == null) + ", Device is null ? " + (usbDevice == null));
if (intent.getBooleanExtra(
UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
Log.d("onReceive", "Connected USB ...");
// 수락했을 경우
showMessage("receiver : USB Host 연결됨.");
}
else {
Log.d("onReceive", "Permission denied....");
Log.d(MainActivity.class.getName(),
"permission denied for accessory " + accessory);
showMessage("permission denied.");
}
openAccessory(accessory);
UsbManager manager = null;
manager = (UsbManager) getSystemService(Context.USB_SERVICE);
HashMap<String, UsbDevice> deviceList = manager
.getDeviceList();
Iterator<UsbDevice> deviceIter = deviceList.values()
.iterator();
while (deviceIter.hasNext()) {
UsbDevice device = deviceIter.next();
// Device's class...
int count = device.getInterfaceCount();
tv01.setText("count:" + count);
for (int i = 0; i < count; i++) {
UsbInterface iface = device.getInterface(i);
tv02.setText(tv02.getText() + "," + iface.getId());
}
}
// 연결 수락 결과를 받았음을 표시
mPermissionRequestPending = false;
tv04.setText("3");
}
}
else
if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
// Android Accessory Protocol을 구현한 장비의 연결이 해제되었을 때
UsbAccessory accessory = intent
.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
// 앱이 사용하고 있는 장비와 같은 것인지 확인
if (accessory != null && accessory.equals(mAccessory)) {
showMessage("USB Host 연결 해제됨.");
closeAccessory();
}
tv04.setText("4");
}
tv04.setText("5");
}
};
private TextView tv01;
private TextView tv02;
private TextView tv03;
private TextView tv04;
/*static class IncomingHandler extends Handler {
private final WeakReference<UDPListenerService> mService;
IncomingHandler(UDPListenerService service) {
mService = new WeakReference<UDPListenerService>(service);
}
#Override
public void handleMessage(Message msg)
{
UDPListenerService service = mService.get();
if (service != null) {
service.handleMessage(msg);
}
}
}*/
/*Handler mIncomingHandler = new Handler(new Handler.Callback() {
#Override
public boolean handleMessage(Message msg) {
}
});*/
static Handler uiHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
Log.d("handleMessage", "msg.what: " + msg.what + ", msg.obj: " + msg.obj);
switch (msg.what) {
case 1:
}
}
};
private UsbAccessory mAccessory;
private AdkHandler handler;
private static UsbManager mUsbManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv01 = (TextView) findViewById(R.id.tv01);
tv02 = (TextView) findViewById(R.id.tv02);
tv03 = (TextView) findViewById(R.id.tv03);
tv04 = (TextView) findViewById(R.id.tv04);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
Log.d("onCreate", "Permission intent getting...");
mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(
ACTION_USB_PERMISSION), 0);
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
filter.addAction(UsbManager.ACTION_USB_ACCESSORY_ATTACHED);
Log.d("onCreate", "registering Receiver..");
Log.d("onCreate", "receiver is null ? " + (mUsbReceiver == null));
registerReceiver(mUsbReceiver, filter);
Log.d("onCreate", "registered Receiver..");
Log.d("onCreate", "Got permission intent...");
tv04.setText("1");
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
/** 액티비티가 화면에 보일 때 호출 */
#Override
public void onResume() {
super.onResume();
Log.d("onResume", "Getting device list");
// 앱이 화면에 보일 때 안드로이드 장비에 Android Accessory Protocol을
// 구현한 USB Host가 연결되어 있는지 확인
HashMap<String, UsbDevice> devices = mUsbManager.getDeviceList();
Log.d("onResume", "Getting UsbAccessory");
UsbAccessory accessory = getIntent().getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
if (accessory != null) { // Android Accessory Protocol를 구현한 장비를 찾았을 경우
Log.d("onResume", "Got accessory");
if (mUsbManager.hasPermission(accessory)) {
Log.d("onResume", "Got permission");
showMessage("onresume : USB Accessory 연결됨.");
openAccessory(accessory);
}
else {
synchronized (mUsbReceiver) {
if (!mPermissionRequestPending) {
mUsbManager.requestPermission(accessory,
mPermissionIntent); // USB 연결을 통해 장비에 연결해도 되는지 사용자에게 문의
mPermissionRequestPending = true; // 연결권한을 물어보드 코드를 실행했음을 표시
}
}
}
}
else {
String device = "";
if (devices != null) {
Set<String> keys = devices.keySet();
for (String key : keys) {
device += key + ": " + devices.get(key).getDeviceName();
}
}
showMessage("mAccessory is null, devices: " + (devices == null ? "null" : device));
Log.d(MainActivity.class.getName(), "mAccessory is null");
}
tv04.setText("2");
}
// 액티비티가 소멸될 때 호출
#Override
protected void onDestroy() {
// 브로드캐스트 리시버를 제거
unregisterReceiver(mUsbReceiver);
super.onDestroy();
}
private void showMessage(String msg){
Log.d("showMessage", msg);
tv03.setText("message: " + msg);
}
private void openAccessory(UsbAccessory accessory){
mAccessory = accessory;
if(handler == null){
Log.d("openAccessory", "Instanciating AdkHandler");
handler = new AdkHandler();
Log.d("openAccessory", "Setting UI Handler to AdkHandler");
handler.setUiHandler(uiHandler);
}
Log.d("openAccessory", "Openning AdkHandler");
handler.open(mUsbManager, mAccessory);
}
private void closeAccessory(){
if(handler != null && handler.isConnected())
handler.close();
mAccessory = null;
}
}
3-1.AdkHandler.java
package com.example.signalhello;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import android.annotation.TargetApi;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
/**
*
* #author Chun, Young-yil. at IBS Inc.
* #since ADK 4.0
* #date 2013. 5. 15.
*/
#TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
public class AdkHandler implements Runnable {
private ParcelFileDescriptor mFileDescriptor;
private FileInputStream mInputStream;
private FileOutputStream mOutputStream;
private Handler uiHandler;
private boolean running;
/* (non-Javadoc)
* #see java.lang.Runnable#run()
*/
#Override
public void run() {
Log.d("run", "start");
int ret = 0;
byte[] buffer = new byte[16384];
int i;
while (ret >= 0 && running) {
try {
ret = mInputStream.read(buffer);
Log.d("run", "" + ret);
}
catch (Exception e) {
e.printStackTrace();
break;
}
i = 0;
Log.d("run", "i: " + i + ", ret: " + ret);
while ( i < ret && running) {
int len = ret - i;
Log.d("run", "buffer[" + i + "]: " + buffer[i]);
switch (buffer[i]) {
case 0x1:
if (len >= 3) {
Message m = Message.obtain(uiHandler, 1);
int value = composeInt(buffer[i = 1], buffer[i + 2]);
m.obj = value;
uiHandler.sendMessage(m);
Log.d("value", "" + value);
}
i += 3;
break;
default :
Log.d("default", "unknown msg:" + buffer[i]);
i = len;
break;
}
}
}
}
/**
* #param b
* #param c
* #return
*/
private int composeInt(byte high, byte low) {
int val = (int) high & 0xff;
val *= 256;
val += (int) low & 0xff;
return val;
}
public void open(UsbManager usbManager, UsbAccessory accessory) {
Log.d("open", "Getting FileDescriptor");
mFileDescriptor = usbManager.openAccessory(accessory);
if (mFileDescriptor == null) {
Log.d("open", "Failed to get ParcelFileDescriptor");
Log.d("보드연결", "실패");
Message msg = Message.obtain(uiHandler, -1);
msg.obj = "보드연결 실패";
Log.d("open", "Sending fail message to UI Handler...");
uiHandler.sendMessage(msg);
}
else
{
Log.d("open", "Succeeded in getting ParcelFileDescriptor");
Log.d("open", "Getting FileDescriptor from ParcelFileDescriptor");
FileDescriptor fd = mFileDescriptor.getFileDescriptor();
Log.d("open", "Getting FileInputStream...");
mInputStream = new FileInputStream(fd);
Log.d("open", "New Threading..");
Thread thread = new Thread(null, this, "ADK Example");
running = true;
Log.d("open", "Starting thread...");
thread.start();
Log.d("보드연결", "성공");
}
}
public void close() {
Log.d("close", "Closing...");
running = false;
}
/**
* 멤버 uiHandler 을 회수
* #return the uiHandler
*/
public Handler getUiHandler() {
return uiHandler;
}
/**
* sets the uiHandler of this instance to given uiHandler.
* 멤버속성 uiHandler 을 인수 uiHandler 으로 세팅.
* #param uiHandler the uiHandler to set
*/
public void setUiHandler(Handler uiHandler) {
this.uiHandler = uiHandler;
}
/**
* #return
*/
public boolean isConnected() {
return (mInputStream != null && mOutputStream != null);
}
}
_4. acivity_main.xml_
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/ll01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:orientation="vertical" >
<TextView
android:id="#+id/tv01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="장비미인식" />
<TextView
android:id="#+id/tv02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
<TextView
android:id="#+id/tv03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
<TextView
android:id="#+id/tv04"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-1" />
</LinearLayout>
</RelativeLayout>
5. logcat ( using adbwireless in rooting MPgio minipad )
05-31 12:16:12.728: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
05-31 12:16:15.298: W/PowerUI(207): unknown intent: Intent { act=android.intent.action.ACTION_POWER_CONNECTED flg=0x10000010 }
05-31 12:16:15.488: I/WindowManager(140): MediaPlayer.is not PlayingVideo
05-31 12:16:15.728: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
05-31 12:16:16.088: I/WindowManager(140): MediaPlayer.is not PlayingVideo
05-31 12:16:17.218: I/USB3G(86): event { 'add', '/devices/platform/sw_hcd_host0/usb1/1-1', 'usb', '', 189, 15 }
05-31 12:16:17.218: I/USB3G(86): path : '/sys/devices/platform/sw_hcd_host0/usb1/1-1'
05-31 12:16:17.218: I/USB3G(86): VID :size 5,vid_path '/sys/devices/platform/sw_hcd_host0/usb1/1-1/idVendor',VID '2341
05-31 12:16:17.218: I/USB3G(86): '.
05-31 12:16:17.218: I/USB3G(86): PID :size 5,Pid_path '/sys/devices/platform/sw_hcd_host0/usb1/1-1/idProduct',PID '003e
05-31 12:16:17.218: I/USB3G(86): '.
05-31 12:16:17.218: I/USB3G(86): cmd=/system/etc/usb_modeswitch.sh /system/etc/usb_modeswitch.d/2341_003e &,
05-31 12:16:17.228: E/EventHub(140): could not get driver version for /dev/input/mouse0, Not a typewriter
05-31 12:16:17.228: D/EventHub(140): No input device configuration file found for device 'Arduino LLC Arduino Due '.
05-31 12:16:17.248: I/EventHub(140): New device: id=15, fd=247, path='/dev/input/event4', name='Arduino LLC Arduino Due ', classes=0x8000000b, configuration='', keyLayout='/system/usr/keylayout/Generic.kl', keyCharacterMap='/system/usr/keychars/Generic.kcm', builtinKeyboard=false
05-31 12:16:17.298: I/USB3G(86): excute ret : 0,err:No such file or directory
05-31 12:16:17.318: I/InputReader(140): Device added: id=15, name='Arduino LLC Arduino Due ', sources=0x00002103
05-31 12:16:17.318: I/ActivityManager(140): Config changed: {1.3 0mcc0mnc ko_KR layoutdir=0 sw640dp w1066dp h592dp lrg land finger qwerty/v/v -nav/h s.33}
05-31 12:16:17.338: D/OpenGLRenderer(1631): Flushing caches (mode 0)
05-31 12:16:17.478: D/Activity(1631): pckname = com.example.signalhello mComponent = com.example.signalhello.MainActivity
05-31 12:16:17.538: I/StatusBar.HeightReceiver(207): Resizing status bar plugged=false height=36 old=36
05-31 12:16:17.658: D/onCreate(1631): Permission intent getting...
05-31 12:16:17.658: D/onCreate(1631): registering Receiver..
05-31 12:16:17.668: D/onCreate(1631): receiver is null ? false
05-31 12:16:17.668: D/onCreate(1631): registered Receiver..
05-31 12:16:17.668: D/onCreate(1631): Got permission intent...
05-31 12:16:17.698: D/onResume(1631): Getting device list
05-31 12:16:17.698: D/onResume(1631): Getting UsbAccessory
05-31 12:16:17.698: D/showMessage(1631): mAccessory is null, devices:
05-31 12:16:17.698: D/com.example.signalhello.MainActivity(1631): mAccessory is null
05-31 12:16:17.728: D/ViewRootImpl(1631): pckname = com.example.signalhello
05-31 12:16:18.138: I/WindowManager(140): MediaPlayer.is not PlayingVideo
05-31 12:16:18.738: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
05-31 12:16:20.068: D/dalvikvm(140): GC_EXPLICIT freed 267K, 24% free 8736K/11399K, paused 8ms+13ms
05-31 12:16:21.738: I/wpa_supplicant(400): [CTRL_IFACE]SIGNAL_POLL
I'm very confused with my situation with above things.
The Arduino board is connected with my notebook PC (programming port). (I think it provides power to the board, doesn't it?) Because the power supply is needed, no other power supplier I have.
And, I compiled Blink.ino which I downloaded from Arduino's site. (I have tested other sketches. But no news.)
And, the board works blinking when uploaded by the Arduino code writing tool.
But when I attached (connected) the board by USB cable to Android device MPgio MiniPad, I have no sign of detection with my codes above.
Just system_process issues some strange messages (which are included above logcat messages) like '05-31 12:16:17.228: E/EventHub(140): could not get driver version for /dev/input/mouse0, Not a typewriter' or '05-31 12:16:17.228: D/EventHub(140): No input device configuration file found for device 'Arduino LLC Arduino Due '.
But, just below those, it prints 'New device: id......' which is from system_process's EventHub Tag.
I want to just detect my Arduino board.

I have searched to solve this problem many sites, blogs etc. And finally I became to have a doubt about that the hardware - MPgio - support this kind of application. Because I found some blogs say all kinds of android device necessarily do not support this. So I called to MPgio customer center to let me contact with technical supervisor or consultant who could answer whether the device supports the ADK - USB Accessory, Host application.
Having talked with another man, I was told to get a call later by another man who has an answer for that.
And I was called when my way to home. And he had asked some questions about my requests, but he couldn't answer by right that time, instead he promised to call me again with answer for this. And finally! I got a call of who made a promise, and he said the device does not support this. And it was kernel problem.
And he added they have a case to install the driver -FTDI? I heard- for distribution of which meets specific client requirements (with payment included, I heard).
... And I am heard that if I need that I must pay or rent - 'lease' I may resume the way he said - this on which is replied that I am not the man who could answer this right the time...
That's all.
But I might have to add some for other developers who might have problems similar to this.
First of all, the Blink.ino is not the good case which has not the code of declaration of ADK instance that might be the protocol which can interface to other supporting device.
Actually, I have tested other codes which have such an announcement. But it didn't make a success anyway - in my case, the device not supported.
And, I have to write a minute thing that the arduino 1.5.2 uses ADK library which replaced
the AndroidAccessory(.h) library being used in earlier version - whiche version I cannot point out specifically.
In some blogs I followed the way of making codes, and imported the AndroidAccessory library , compiled to failure. So I went further, and another blogs I found the case 1.5.2 uses the ADK - the site is
'http://arduino-er.blogspot.kr/2013/03/hello-world-adk-communication-between.html'.
Actually this sites is the final case I am referencing for my hello codes now.
But that sure failed to work in success - in my case, the device problem I mentioned.
If other things happen about this which have to be posted, I will write those again.
Thank you all who has made an effort to solve this anyway...

After my first own answering, I had to know about the devices which might be compatible with ADK 2012, I asked about that to Arduino google group -https://groups.google.com/a/arduino.cc/group/developers/browse_thread/thread/955aa9342270c2a2/8e03022da7aeab3f#8e03022da7aeab3f - and to another Korean site named 'Hardroid' -
http://hardroid.net, and was replied with messages
which he wasn't sure that he could name the compatible devices
specifically.
But he was much sure that the reference phones and tablets from Google
Nexus series would compatible with ADK which might be adopted in
Arduino Due I'm using.

The result is this. We, my company has decided to change the model of tablet, and the board. What surprised me is that the ADK.h in newer version of Arduino board does not work with new tablet working on Jelly Bean (Android SDK 4.2.2) while AndroidAccessory.h does work.
I almost omitted the fact we changed the board from Due to Mega_ADK.
I heard that the Due does not work with ADK properly from my colleage who contacted the vendor in Korea, but actually I can't believe this because I had seen the U-tube file working Due with
device I don't remember the model (probably HTC's).
I'd finished USB-Accessory job with newer tablet ASUS Memo-pad with success.
I don't know the exact reason of not working with ADK.h in sketch right now.

Related

WebSocket works on PC but not on Android?

I'm trying to communicate with an ESP8266 WiFi chip from an Android device using WebSockets to remotely control some motors connected to an Arduino. First I prototyped using a PC & Python & set up a WebSocket server on the ESP8266...
ESP8266_server.ino
#include <ESP8266WiFi.h>
#include <WebSocketsServer.h>
const char* ssid = "SKYNET";
const char* password = "yourdogsauntsmaidenname";
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t lenght) {
//Serial.printf("[%u] get Message: %s\r\n", num, payload);
switch(type) {
case WStype_DISCONNECTED:
break;
case WStype_CONNECTED:
{
IPAddress ip = webSocket.remoteIP(num);
// Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload);
}
break;
case WStype_TEXT:
{
//Serial.printf("[%u] get Text: %s\r\n", num, payload);
String _payload = String((char *) &payload[0]);
Serial.print(_payload);
}
break;
case WStype_BIN:
{
hexdump(payload, lenght);
}
// echo data back to browser
webSocket.sendBIN(num, payload, lenght);
break;
}
}
void setup() {
// Set up serial comms
Serial.begin(115200);
// Set up WiFi
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
// Serial.print(".");
delay(200);
}
// Serial.println("");
// Serial.println("WiFi connected");
// Serial.println("IP address: ");
// Serial.println(WiFi.localIP());
delay(500);
// Set up web socket
// Serial.println("Start Websocket Server");
webSocket.begin();
webSocket.onEvent(webSocketEvent);
}
void loop() {
webSocket.loop();
}
The WiFi chip is connecetd via a serial connection to an Arduino Mega which in turn parses the data to control some H-bridges for 2 DC motors. The Arduino also relays the data to the Arduino IDE serial monitor.
motor_control.ino
// Serial comms from Wemos EPS8622 to Arduino Mega
#include "SoftPWM.h"
// Outputs to PWM & H bridge direction
// PWMs:
// DC_pwm, left_pwm, right_pwm = 3, 4, 5
int pwm_out[] = {3, 4, 5};
const int num_pwm = sizeof(pwm_out) / sizeof(pwm_out[0]);
// H bridge direction control:
// right_2, right_1, left_2, left_1, dc_2, dc_1 = 6, 7, 8, 9, 10 ,11
int dir_pins[] = {6, 7, 8, 9, 10 , 11};
const int num_dir_pins = sizeof(dir_pins) / sizeof(dir_pins[0]);
// Input buffer from ESP8266
int in_buff[] = {0, 0};
const int num_in_buff = sizeof(in_buff) / sizeof(in_buff[0]);
void setup() {
// Set up serial comms
Serial.begin(115200); // Debug to Serial Monitor
Serial3.begin(115200); // From ESP8266
// Set up PWM pins
SoftPWMBegin();
for (int i = 0; i < num_pwm; i++)
{
SoftPWMSet(pwm_out[i], 0);
}
// Set up H bridge direction pins
for (int i = 0; i < num_dir_pins; i++)
{
pinMode(dir_pins[i], OUTPUT);
digitalWrite(dir_pins[i], LOW);
}
}
void loop() {
// Check input from EPS8266 & send it to the H bridges
while (Serial3.available() < num_in_buff){}
if (Serial3.available()) {
// read the incoming bytes
// in_buff[0] - direction flags
// in_buff[1] - PWM
Serial.println(".......");
Serial.println("In from ESP8266");
for (int i = 0; i < num_in_buff; i++){
in_buff[i] = Serial3.read();
Serial.println(in_buff[i]);
}
Serial.println(".......");
}
// Set direcions on H bridges
Serial.println("Direction pins");
for (int i = 0; i < num_dir_pins; i++)
{
digitalWrite(dir_pins[i], bitRead(in_buff[0], i));
Serial.print("pin ");
Serial.print(dir_pins[i]);
Serial.print(" : ");
Serial.print(digitalRead(dir_pins[i]));
Serial.println();
}
// PWM to motors
for (int i = 0; i < num_pwm; i++)
{
SoftPWMSet(pwm_out[i], in_buff[1]);
}
}
On the PC side I have some Python code that is set up as a WebSocket client that takes user input from the terminal & transmits to the ESP chip.
motor_control_WiFi.py
"""
Motor control over WiFi using Wemos EPS8266 & Mega board
Motor H-bridge direction flags
Both forwards - b'111001, d'57, ASCII 9
Both backwards - b'110110, d'54, ASCII 6
Clockwise (right) - b'111010, d'58, ASCII :
A/Clock (left) - b'110101, d'53, ASCII 5
"""
from ws4py.client.threadedclient import WebSocketClient
import time, requests
import struct
esp8266host = "ws://192.168.1.84:81/"
class DummyClient(WebSocketClient):
def opened(self):
print("Websocket open")
def closed(self, code, reason=None):
print("Connexion closed down", code, reason)
def received_message(self, m):
print(m)
if __name__ == '__main__':
try:
ws = DummyClient(esp8266host)
ws.connect()
print("Ready !")
direction = ""
while direction != "q":
direction = input("Direction: ")
if direction == "f":
payload = "9"
if direction == "b":
payload = "6"
if direction == "r":
payload = ":"
if direction == "l":
payload = "5"
ws.send(payload)
time.sleep(.20)
pwm_out = int(input("PWM: "))
pwm_out = struct.pack('<B', pwm_out)
ws.send(pwm_out)
time.sleep(.20)
print("Finished, close Websocket connexion now and exit script")
ws.send("0:0")
ws.close()
exit()
except KeyboardInterrupt:
ws.send("0:0")
ws.close()
This all works fine. So my next step was to make an Android app to do what my Python code is doing. I'm using the okhttp3 library & added implementation 'com.squareup.okhttp3:okhttp:3.6.0' to the Gradle build file & added internet permissions to the manifest.
MainActivity.java
package qdivision.org.websocketexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;
public class MainActivity extends AppCompatActivity {
private Button start;
private TextView output;
private OkHttpClient client;
private final class EchoWebSocketListener extends WebSocketListener {
private static final int NORMAL_CLOSURE_STATUS = 1000;
#Override
public void onOpen(WebSocket webSocket, Response response) {
//webSocket.send("l");
webSocket.send(ByteString.decodeHex("23"));
webSocket.send(ByteString.decodeHex("32"));
webSocket.close(NORMAL_CLOSURE_STATUS, "Goodbye !");
}
#Override
public void onMessage(WebSocket webSocket, String text) {
output("Receiving : " + text);
}
#Override
public void onMessage(WebSocket webSocket, ByteString bytes) {
output("Receiving bytes : " + bytes.hex());
}
#Override
public void onClosing(WebSocket webSocket, int code, String reason) {
webSocket.close(NORMAL_CLOSURE_STATUS, null);
output("Closing : " + code + " / " + reason);
}
#Override
public void onFailure(WebSocket webSocket, Throwable t, Response response) {
output("Error : " + t.getMessage());
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = (Button) findViewById(R.id.start);
output = (TextView) findViewById(R.id.output);
client = new OkHttpClient();
start.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
start();
}
});
}
private void start() {
Request request = new Request.Builder().url("ws://192.168.1.84:81").build(); //"ws://echo.websocket.org"
EchoWebSocketListener listener = new EchoWebSocketListener();
WebSocket ws = client.newWebSocket(request, listener);
client.dispatcher().executorService().shutdown();
}
private void output(final String txt) {
runOnUiThread(new Runnable() {
#Override
public void run() {
output.setText(output.getText().toString() + "\n\n" + txt);
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="qdivision.org.websocketexample.MainActivity">
<Button
android:id="#+id/start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="Start !"
android:layout_marginTop="40dp"
android:textSize="17sp"/>
<TextView
android:id="#+id/output"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/start"
android:layout_centerHorizontal="true"
android:textSize="16sp"
android:layout_marginTop="30dp"/>
</RelativeLayout>
When this is deployed I dont get any connection errors. The sent bytes are echoed back to the display & the client disconnects with no error. BUT I get no feed back via the Arduino Serial Monitor that anything has been sent!
What's missing here? How come no connection error if the bytes are not being sent/recieved?
Edit #1 I ran the Python code on the Android device from the Termux command line. The code runs, says the socket is open & lets me input direction & PWM but still nothing from the serial monitor.
Edit #2 I can ping the ESP8266 from the Android device using Termux with 0 package loss but still no data being sent by either the Python code or the app.
Edit #3 Python code now works from the Termux command line on the Android device (no idea how I made no changes, it just works now??!!??). The okhttp3 based app still sends no data.

My android phone is not sending signals to the arduino uno or maybe the arduino uno card is not communicating to the servo motor sg90

I am uploading the code of both the android-studio as well as the arduino uno.. It seems right but somehow it doesn't work
Android Studio code :
package com.example.chintan.doorlock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;
import android.os.Handler;
public class MainActivity extends AppCompatActivity {
private final String DEVICE_ADDRESS = "00:21:13:01:ED:10"; //MAC Address of Bluetooth Module
private final UUID PORT_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private BluetoothDevice device;
private BluetoothSocket socket;
private OutputStream outputStream;
private InputStream inputStream;
Thread thread;
byte buffer[];
boolean stopThread;
boolean connected = false;
String command;
Button lock_state_btn, bluetooth_connect_btn;
TextView lock_state_text;
ImageView lock_state_img;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lock_state_btn = (Button) findViewById(R.id.lock_state_btn);
bluetooth_connect_btn = (Button) findViewById(R.id.bluetooth_connect_btn);
lock_state_text = (TextView) findViewById(R.id.lock_state_text);
lock_state_img = (ImageView) findViewById(R.id.lock_state_img);
bluetooth_connect_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
if(BTinit()) //initialises bluetooth
{
BTconnect(); //connects android code to arduino
beginListenForData();
// The code below sends the number 3 to the Arduino asking it to send the current state of the door lock so the lock state icon can be updated accordingly
command = "3";
try
{
outputStream.write(command.getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
});
lock_state_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
if(connected == false)
{
Toast.makeText(getApplicationContext(), "Please establish a connection with the bluetooth servo door lock first", Toast.LENGTH_SHORT).show();
}
else
{
command = "1";
try
{
outputStream.write(command.getBytes()); // Sends the number 1 to the Arduino. For a detailed look at how the resulting command is handled, please see the Arduino Source Code
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
});
}
void beginListenForData() // begins listening for any incoming data from the Arduino
{
final Handler handler = new Handler();
stopThread = false;
buffer = new byte[1024];
Thread thread = new Thread(new Runnable()
{
public void run()
{
while(!Thread.currentThread().isInterrupted() && !stopThread)
{
try
{
int byteCount = inputStream.available();
if(byteCount > 0)
{
byte[] rawBytes = new byte[byteCount];
inputStream.read(rawBytes);
final String string = new String(rawBytes, "UTF-8");
handler.post(new Runnable()
{
public void run()
{
if(string.equals("3"))
{
lock_state_text.setText("Lock State: LOCKED"); // Changes the lock state text
lock_state_img.setImageResource(R.drawable.locked_icon); //Changes the lock state icon
}
else if(string.equals("4"))
{
lock_state_text.setText("Lock State: UNLOCKED");
lock_state_img.setImageResource(R.drawable.unlocked_icon);
}
}
});
}
}
catch (IOException ex)
{
stopThread = true;
}
}
}
});
thread.start();
}
#Override
protected void onStart()
{
super.onStart();
}
}
And this is my arduino source code :
//Android-controlled Arduino Bluetooth Servo Door Lock by uscv
#include <Servo.h>
#include <EEPROM.h>
Servo servo;
char state;
void setup() {
// put your setup code here, to run once:
servo.attach(7);
if(EEPROM.read(0) == 1) // Reads the EEPROM value stored to know what state the door lock was in before it was last turned off
{ // An EEPROM value of 1 means UNLOCKED and a value of 2 means LOCKED
servo.write(0); // Rotates the servo to the unlocked position
delay(200);
}
else if(EEPROM.read(0) == 2)
{
servo.write(75); // Rotates the servo to the locked position
delay(200);
}
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available() > 0)
{
char data;
data = Serial.read(); // The variable data is used to store the value sent by the Android app
switch(data)
{
case '1':
if(EEPROM.read(0) == 1) //An EEPROM value of 1 means it is currently unlocked
{
EEPROM.write(0, 2); // Writes the number 2 to address 0 on the Arduino's EEPROM. This value will be used by the Arduino to remember the last state the door lock was in
Serial.print("3"); // Sends the number 3 to the Android app. To see what this does, please see the Android Studio Project file
servo.write(75);
delay(15);
}
else if(EEPROM.read(0) == 2) //An EEPROM value of 2 means it i currently locked
{
EEPROM.write(0, 1); // Writes the number 1 to address 0 on the Arduino's EEPROM. This value will be used by the Arduino to remember the last state the door lock was in
Serial.print("4"); // Sends the number 4 to the Android app. The number sent will be used by the app to update the locked/unlocked icon
servo.write(0);
delay(15);
}
break;
case '3':
if(EEPROM.read(0) == '1')
{
Serial.print("4");
}
else if(EEPROM.read(0) == '2')
{
Serial.print("3");
}
break;
}
}
}
So, first the android app will start bluetooth, then connect to the arduino uno card and then perform the following functions:
1. "3" sent from android phone to arduino
2. received either "4" or "3" based on its status from arduino uno to android
3. Change the lock image on the android phone
4. send "1" from the android phone to the arduino
5. Change the status of the servo motor sg90 from its current position
Now, my android application is error-free and connects to the arduino uno and also is able to start the bluetooth of the phone. It establishes the connection but does not change the position of the servo motor sg90. I dont understand the problem what should we do?
You are calling EEPROM.read() before initializating the EEPROM. In other words for example in your setup() you are checking whether you EEPROM address 0 contains a certain value rather than initialization it with a certain value. Then
in your loop(), again you are checking whether EEPROM address contains a certain value before any value is written to the EEPROM and thus you will never reach the EEPROM write part because your if statements always returns false. So, start first by writing a value to EEPROM address 0.

Send about ten two digit numbers at a time to a Bluetooth device at random intervals

I am building a BLE remote controller application.
I am paring a BLE device with the Android phone with the tested and working code below.
Intent intentOpenBluetoothSettings = new Intent();
intentOpenBluetoothSettings.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intentOpenBluetoothSettings);
I want to connect to one of the devices in the paired list, and I know the name, which is always the same.
Later, I want to send about ten two digit numbers at a time to that device at random intervals (from a listener for a button), and I don't need any information back. Simplex communication only, Android phone to BLE device.
#Override
public void uiDeviceFound(final BluetoothDevice device, final int rssi, final byte[] record )
{
String msg ;
String deviceName = device.getName() ;
String redRacer = "Red Racer" ;
if (redRacer.equals(deviceName))
{
boolean status ;
status = mBleWrapper.connect(device.getAddress().toString()) ;
if (status == false)
{
msg = "Sorry, could not connect to Red Racer" ;
Toast.makeText(SecondaryActivity.this,msg,Toast.LENGTH_SHORT).show() ;
}
else
{
msg = "Connected to Red Racer" ;
Toast.makeText(SecondaryActivity.this,msg + " " + deviceName + " " + redRacer,Toast.LENGTH_SHORT).show() ;
}
}
}
During my research to resolve the issue I found this brief, but informative article on the differences between pairing and bonding as far as BLE is concerned:
https://piratecomm.wordpress.com/2014/01/19/ble-pairing-vs-bonding/
Giving credit where credit is due. The above code which resolved my issue was taken from Getting Started with Bluetooth Low Energy (O'REILLY), although the code copied directly from their book continually crashed the activity whenever it was called. After correcting the problems, as per the above code, it works flawlessly. Now that the connection is made, I have to push my control code out the established link to the Simblee chip on my slave board.
Overall the code is what I would define as plug-in reusable code which I think will be applicable to others who might want the same functionality. I will post the complete code, once I have it up and running.
package com.my_android_app.my_android_app;
import android.app.Activity ;
import android.content.Intent ;
import android.content.SharedPreferences ;
import android.content.pm.PackageManager ;
import android.os.Bundle ;
import android.os.Handler ;
import android.support.v7.app.AppCompatActivity ;
import android.util.Log ;
import android.view.Gravity ;
import android.view.View ;
import android.widget.Button ;
import android.widget.TextView ;
import android.widget.Toast ;
import java.util.List ;
import java.util.UUID ;
import java.util.Calendar ;
import android.bluetooth.BluetoothAdapter ;
import android.bluetooth.BluetoothDevice ;
import android.bluetooth.BluetoothGatt ;
import android.bluetooth.BluetoothGattCharacteristic ;
import android.bluetooth.BluetoothGattService ;
public class BLE_Test_Activity extends AppCompatActivity {
public BLE_Test_Activity.mSensorState mState ;
private enum mSensorState {IDLE, ACC_ENABLE, ACC_READ} ;
boolean connectedTo = false ;
boolean okButtonClicked = false ;
boolean receivedRSSI = false ;
private byte[] mRawValue = null ;
private int mIntValue = 0 ;
private String mAsciiValue = "" ;
private String mStrValue = "" ;
private String mLastUpdateTime = "" ;
private boolean mNotificationEnabled = false ;
private final String LOGTAG = "BLETEST" ;
private final String TARGET_BLE = "My BLE Device" ;
private String gattList = "" ;
private int rssi_1 = 0 ;
private int rssi_2 = 0 ;
private int rssi_3 = 0 ;
private int rssi_4 = 0 ;
private int valueRSSI = 0 ;
private String mDeviceRSSI ;
private TextView mDeviceStatus ;
private TextView mDeviceRssiView ;
private String mDeviceAddress ;
private static final long SCANNING_TIMEOUT = 5 * 1000; /* 5 seconds */
// The UUID variable values below are only applicable to the RFD77101 BLE chip.
// Enter values here which are applicable to the BLE device you are using.
private static final UUID
UUID_SIMBLEE_SERVICE = UUID.fromString("0000fe84-0000-1000-8000-00805f9b34fb") ,
UUID_SIMBLEE_CHARACTERISTIC_2 = UUID.fromString("2d30c083-f39f-4ce6-923f-3484ea480596") ;
private boolean mScanning = false ;
private Handler mHandler = new Handler() ;
private BleWrapper mBleWrapper = null ; // Add this line to instantiate the BLE wrapper
private BluetoothGattCharacteristic mCharacteristic = null ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState) ;
setContentView(R.layout.activity_ble__test_) ;
connectViewsVariables() ;
final String dataSentMessage = "Your " + TARGET_BLE + " put your transmitted message here." ;
mBleWrapper = new BleWrapper(this, new BleWrapperUiCallbacks.Null() {
#Override
public void uiDeviceFound(final BluetoothDevice device, final int rssi, final byte[] record) {
if (TARGET_BLE.equals(device.getName())) {
if (mBleWrapper.connect(device.getAddress())) {
// Toast.makeText(BLE_Test_Activity.this, device.getAddress(), Toast.LENGTH_SHORT).show(); // This is included for debugging purposes
} else {
Toast.makeText(BLE_Test_Activity.this, "Sorry, could not connect to " + TARGET_BLE, Toast.LENGTH_SHORT).show();
}
}
} // ********************** uiDeviceFound *************************************
public void uiDeviceConnected(final BluetoothGatt gatt, final BluetoothDevice device) {
runOnUiThread(new Runnable() {
#Override
public void run() {
mDeviceStatus.setText ("connected ") ;
mDeviceRssiView.setText ("measuring .") ;
connectedTo = true;
}
});
} // ********************** uiDeviceConnected *************************************
public void uiDeviceDisconnected(final BluetoothGatt gatt, final BluetoothDevice device) // Takes about 20 seconds to display disconnected,
{ // then more than thirty minutes to reconnect.
runOnUiThread(new Runnable() {
#Override
public void run() {
mDeviceStatus.setText ("disconnected") ;
mDeviceRssiView.setText("disconnected") ;
connectedTo = false;
}
});
} // ********************** uiDeviceDisconnected *************************************
#Override
public void uiCharacteristicForService( BluetoothGatt gatt,
BluetoothDevice device,
BluetoothGattService service,
List<BluetoothGattCharacteristic> chars)
{
super.uiCharacteristicForService(gatt, device, service, chars);
for (BluetoothGattCharacteristic c : chars)
{
String charName = BleNamesResolver.resolveCharacteristicName(c.getUuid().toString()) ;
gattList += "Characteristic: " + charName + "\n" ;
}
} // ********************** uiCharacteristicForService *************************************
public void uiNewRssiAvailable(final BluetoothGatt gatt, final BluetoothDevice device, final int rssi) {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (rssi_4 == 0)
{
mDeviceRSSI = "measuring ....." ;
mDeviceRssiView.setText(mDeviceRSSI) ;
}
if (rssi_3 == 0)
{
mDeviceRSSI = "measuring ...." ;
mDeviceRssiView.setText(mDeviceRSSI) ;
}
if (rssi_2 == 0)
{
mDeviceRSSI = "measuring ..." ;
mDeviceRssiView.setText(mDeviceRSSI) ;
}
if (rssi_1 == 0)
{
mDeviceRSSI = "measuring .." ;
mDeviceRssiView.setText(mDeviceRSSI) ;
}
rssi_4 = rssi_3 ;
rssi_3 = rssi_2 ;
rssi_2 = rssi_1 ;
rssi_1 = rssi ;
if (rssi_4 != 0) {
valueRSSI = (rssi_1 + rssi_2 + rssi_3 + rssi_4) / 4 ; // This is a simple moving average to filter out noise
mDeviceRSSI = (valueRSSI) + " dBm" ;
mDeviceRssiView.setText(mDeviceRSSI) ;
}
receivedRSSI = true ;
}
}) ;
if (okButtonClicked)
{
okButtonClicked = false ;
// Build up newValue with the data you want to send out the BLE link.
// I have hard coded 0202 just for testing purposes.
// Make sure the contents of newValue is Hex only 0 - 9, A - F
String newValue = "0202" ;
byte[] dataToWrite = parseHexStringToBytes(newValue) ;
BluetoothGattCharacteristic mCharacteristic ;
mCharacteristic = gatt.getService(UUID_SIMBLEE_SERVICE).getCharacteristic(UUID_SIMBLEE_CHARACTERISTIC_2) ;
mBleWrapper.writeDataToCharacteristic(mCharacteristic, dataToWrite) ;
}
} // *************************** uiNewRssiAvailable ***********************************************
#Override
public void uiNewValueForCharacteristic(BluetoothGatt gatt,
BluetoothDevice device,
BluetoothGattService service,
BluetoothGattCharacteristic ch,
String strValue,
int intValue,
byte[] rawValue,
String timestamp)
{
super.uiNewValueForCharacteristic(gatt, device, service, ch, strValue, intValue, rawValue, timestamp);
for (byte b:rawValue)
{
Log.d(LOGTAG,"Val: + b") ;
}
} // ********************** uiNewValueForCharacteristic *************************************
#Override
public void uiGotNotification( BluetoothGatt gatt,
BluetoothDevice device,
BluetoothGattService service,
BluetoothGattCharacteristic characteristic)
{
super.uiGotNotification(gatt, device, service, characteristic) ;
String ch = BleNamesResolver.resolveCharacteristicName(characteristic.getUuid().toString()) ;
Log.d(LOGTAG,"uiGotNotification: " + ch) ;
} // *************************** uiNewValueForCharacteristic *************************************
} ) ; // *************************** new BleWrapper **************************************************
if (!mBleWrapper.checkBleHardwareAvailable()) {
Toast.makeText(this, "No BluetoothLE compatible hardware detected", Toast.LENGTH_SHORT).show() ;
finish() ;
} // ********************** checkBleHardwareAvailable *************************************
Button activity6Button = (Button) findViewById(R.id.button6); // Green check mark button
activity6Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (connectedTo)
{
okButtonClicked = true ;
if (receivedRSSI)
{
Toast toast = Toast.makeText(BLE_Test_Activity.this, dataSentMessage, Toast.LENGTH_SHORT) ;
TextView v = (TextView) toast.getView().findViewById(android.R.id.message) ;
if (v != null) v.setGravity(Gravity.CENTER) ;
toast.show() ;
receivedRSSI = false ;
}
}
SharedPreferences prefs = getSharedPreferences("saveUserSettings", MODE_PRIVATE);
SharedPreferences.Editor editor = prefs.edit() ;
editor.putString("AppIsOn", "yes") ;
editor.apply() ;
}
}) ; // ********************** green check mark *************************************
Button activity7Button = (Button) findViewById(R.id.button7); // Blue back arrow
activity7Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
setResult(Activity.RESULT_CANCELED) ; // Page 60 Sams
finish() ;
}
}) ; // ********************** back arrow *************************************
} // ********************************** onCreate ********************************************
public byte[] parseHexStringToBytes(final String hex) {
String tmp = hex.substring(2).replaceAll("[^[0-9][a-f]]", "") ;
byte[] bytes = new byte[tmp.length() / 2] ; // every two letters in the string are one byte finally
String part = "" ;
for(int i = 0; i < bytes.length; ++i) {
part = "0x" + tmp.substring(i*2, i*2+2) ;
bytes[i] = Long.decode(part).byteValue() ;
}
return bytes ;
} // ********************** parseHexStringToBytes *************************************
#Override
protected void onResume() {
super.onResume();
if (!mBleWrapper.isBtEnabled()) // Check for Bluetooth enabled on each resume
{
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) ;
startActivity(enableBtIntent) ;
Toast.makeText(BLE_Test_Activity.this, "Sorry but BluetoothLE is not supported on your phone", Toast.LENGTH_SHORT).show() ;
finish() ;
}
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(BLE_Test_Activity.this, "mBleWrapper.isBtEnabled", Toast.LENGTH_SHORT).show() ;
finish() ;
return ;
}
connectedTo = false ;
mBleWrapper.initialize() ;
mDeviceStatus.setText ("searching ...") ;
mDeviceRssiView.setText("searching ...") ;
mBleWrapper.startScanning() ;
} // ************************************ onResume **********************************************
#Override
protected void onStart() {
super.onStart();
} // *********************************** onStart *******************************
#Override
protected void onPause() {
connectedTo = false ;
super.onPause() ;
mBleWrapper.stopScanning() ;
mBleWrapper.diconnect() ;
mBleWrapper.close() ;
} // ********************** onPause *************************************
#Override
protected void onStop() {
SharedPreferences prefs = getSharedPreferences("saveUserSettings", MODE_PRIVATE) ;
SharedPreferences.Editor editor = prefs.edit() ;
editor.putString("AppIsOn", "no") ;
editor.apply() ;
mBleWrapper.stopScanning() ;
mBleWrapper.diconnect() ;
mBleWrapper.close() ;
super.onStop() ;
} // ********************** onStop *************************************
#Override
protected void onDestroy() {
SharedPreferences prefs = getSharedPreferences("saveUserSettings", MODE_PRIVATE) ;
SharedPreferences.Editor editor = prefs.edit() ;
editor.putString("AppIsOn", "no") ;
editor.apply() ;
mBleWrapper.stopScanning() ;
mBleWrapper.diconnect() ;
mBleWrapper.close() ;
super.onDestroy() ;
} // ********************** onDestroy *************************************
private void connectViewsVariables() {
mDeviceStatus = (TextView) findViewById(R.id.peripheral_status) ;
mDeviceRssiView = (TextView) findViewById(R.id.peripheral_rssi) ;
} // ********************** connectViewsVariables ********************************
} // ***************************** BLE_Test_Activity *****************************
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/ble_test"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:background="#FFFFFF"
tools:context="com.my_android_app.my_android_app.BLE_Test_Activity">
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/peripheral_status"
android:gravity="center"
android:layout_marginTop="10dp"
android:layout_below="#+id/textView20"
android:layout_toStartOf="#+id/button39" />
<TextView
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/peripheral_rssi"
android:layout_marginLeft="200dp"
android:layout_marginTop="10dp"
android:layout_below="#+id/textView20" />
<Button
android:layout_width="50dp"
android:layout_height="50dp"
android:textAllCaps="false"
style="#style/Widget.AppCompat.Button.Borderless"
android:id="#+id/button7"
android:background="#drawable/returnicon"
android:layout_alignParentBottom="true"
android:layout_toEndOf="#+id/button39"
android:layout_marginStart="46dp" />
<Button
android:layout_width="50dp"
android:layout_height="50dp"
android:textAllCaps="false"
style="#style/Widget.AppCompat.Button.Borderless"
android:id="#+id/button6"
android:background="#drawable/checkmark"
android:layout_alignParentBottom="true"
android:layout_toStartOf="#+id/button39"
android:layout_marginEnd="44dp" />
</RelativeLayout>
Resources used by this demo.
https://www.bluetooth.com/develop-with-bluetooth/developer-resources-tools/app-acc-2 Download the Bluetooth Application Accelerator kit here, it contains several classes you will need to make this demo work, along with working Java code you can use in you app.
The BLE Demo app included in this kit is formatted for Android Studio thankfully. The BLE Demo app is excellent. In addition to being built around the BLE wrapper which is part of the the Applicaton Accelerator, the BLE Demo drills down into your BLE devices and displays all parameters and their values. The value of this can not be underestimated because in my case, the manufacturer of the BLE device I am using did not even document the UUIDs for the services and characteristics I needed to write to.
https://github.com/microbuilder/IntroToBLE Here is the source code from the excellent book 'Getting Started with Bluetooth Low Energy', O'REILLY. If all you want to do is read and write to a BLE device, this book contains far to much information, especially the marketing information for BLE, however the tutorial for Android development is excellent. Be aware that there are mistakes in the sample code in the book, and the sample code is not the same, but is similar as per this download.
https://evothings.com/2.1/doc/tutorials/how-to-connect-to-ble-devices.html This is an excellent tutorial on connecting with a BLE device with JavaScript which is useless of course for a Java program, however the connection methodology is the same. Also this tutorial explains in simple terms the sequence of events which are required to connect to a BLE device.
https://piratecomm.wordpress.com/category/bluetooth-le Here is a brief, but excellent article on Pairing and Bonding, relative to BLE devices.
Usage instructions:
Install the BLE Demo app from the Bluetooth application accelerator onto your Android phone.
Copy several classes from the BLE Demo app and put them into your app.
These classes are: BleWrapper, BleNamesResolver, BleDefinedUUIDs, BleWrapperUiCallbacks and FetchAddressIntentService.
Create a new empty activity in your app which you will use to place switches, seek bars etc. whose values you wish to send out the BLE link.
Copy and paste the BLE_JAVA into the class created by the new activity you just created.
Replace every occurrence of my_android_app with whatever is applicable for your app.
Replace every occurrence of BLE_Test_Activity with whatever is applicable for your activity.
For the string private final String TARGET_BLE = "My BLE Device" , put the device name of your target device at "My BLE Device" .
In the section private static final UUID, you will need to enter the UUID values applicable to your device. You can use the BLE Demo app to find them if you do not know what they are.
Copy and paste the BLE_XML into the XML file which was just created, and replace every occurrence of my_android_app with whatever is applicable for your app.
Replace every occurrence of BLE_Test_Activity with whatever is applicable for your activity.
I have included a stripped down version of my manifest for an example which I feel has the necessary ingredients for the BLE implementation.
Now you can put the switches, seek bars, etc. into the new activity you just created, and put the values of those controls in the string, 'newValue' which will be the data which will be sent out via BLE.
I hope I have included all necessary steps, if not please let me know so that I can make the applicable changes.
Here is the answer to my own question which was, is there any copy an paste code to implement a simple open loop control system with BLE, with the phone being the master which sends control codes to a BLE slave which can control several real world devices, like motors, lights, heaters, etc.
First of all, I realize an open loop control system is the least desirable control system there is, but in my case the Simblee RFD77101 does not have a characteristic which will return the value written to it, so a closed loop control system is not possible.
Eventually I would like to embellish this code to include read capabilities, etc. but that is not a current priority for me.
Finally, I am a complete newbie at Android/Java development, so if you have any comments or questions, please be nice, and I will do what I can.

Monitor the IP addresses from connections being made from all apps using the network without rooting the Android phone

I am attempting to build an Android app (without having to root the phone) which collects the IP addresses from all the apps' network connections to and from the phone.
I have been tasked with this project and the key point is that the phone must stay unrooted - this (to my knowledge) means I can't use tcpdump or libpcap, since both seem to need the phone to be rooted. One other point, I have found solutions where a VPN Service is used, but, if possible, I am not suppose to use this feature as well, since the app is suppose to work on it's own - without any 'outside' help.
I have been all over stack overflow and many many other sites, trying to find a method to monitor/collect IP addresses and all the solutions I've found required rooting the Android phone. This led me to believe that it wasn't possible, until I found the following app on Google Play.
https://play.google.com/store/apps/details?id=com.borgshell.connectiontrackerfree&hl=en
This app does much more than I need, but it somehow shows the IP addresses of network connections each app is making.
To summarize:
Does anyone know a way to collect IP addresses from internal app's network connections
without rooting the phone
without using a VPN service
Thank you
For all those who are curious about this same issue, I was able to finally figure out how to accomplish this task, without rooting the phone or using a VPN service.
The key to solving this issue, is to look in the following directory on the phone:
/proc/net/(tcp, tcp6, udp, udp6, etc)
Also, here is some code from an open source project that does basically what I was looking for.
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.net.cts;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Pattern;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
public class ListeningPortsTest extends TestCase {
/** Address patterns used to check whether we're checking the right column in /proc/net. */
private static final List<String> ADDRESS_PATTERNS = new ArrayList<String>(2);
static {
ADDRESS_PATTERNS.add("[0-9A-F]{8}:[0-9A-F]{4}");
ADDRESS_PATTERNS.add("[0-9A-F]{32}:[0-9A-F]{4}");
}
/** Ports that are allowed to be listening on the emulator. */
private static final List<String> EXCEPTION_PATTERNS = new ArrayList<String>(6);
static {
// IPv4 exceptions
EXCEPTION_PATTERNS.add("00000000:15B3"); // 0.0.0.0:5555 - emulator port
EXCEPTION_PATTERNS.add("0F02000A:15B3"); // 10.0.2.15:5555 - net forwarding for emulator
EXCEPTION_PATTERNS.add("[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4 Loopback
// IPv6 exceptions
EXCEPTION_PATTERNS.add("[0]{31}1:[0-9A-F]{4}"); // IPv6 Loopback
EXCEPTION_PATTERNS.add("[0]{16}[0]{4}[0]{4}[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4-6 Conversion
EXCEPTION_PATTERNS.add("[0]{16}[F]{4}[0]{4}[0-9A-F]{6}7F:[0-9A-F]{4}"); // IPv4-6 Conversion
}
public void testNoListeningTcpPorts() {
assertNoListeningPorts("/proc/net/tcp", true);
}
public void testNoListeningTcp6Ports() {
assertNoListeningPorts("/proc/net/tcp6", true);
}
public void testNoListeningUdpPorts() throws Exception {
assertNoListeningUdpPorts("/proc/net/udp");
}
public void testNoListeningUdp6Ports() throws Exception {
assertNoListeningUdpPorts("/proc/net/udp6");
}
private static final int RETRIES_MAX = 6;
/**
* UDP tests can be flaky due to DNS lookups. Compensate.
*/
private static void assertNoListeningUdpPorts(String procFilePath) throws Exception {
for (int i = 0; i < RETRIES_MAX; i++) {
try {
assertNoListeningPorts(procFilePath, false);
return;
} catch (ListeningPortsAssertionError e) {
if (i == RETRIES_MAX - 1) {
throw e;
}
Thread.sleep(2 * 1000 * i);
}
}
throw new IllegalStateException("unreachable");
}
private static void assertNoListeningPorts(String procFilePath, boolean isTcp) {
/*
* Sample output of "cat /proc/net/tcp" on emulator:
*
* sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid ...
* 0: 0100007F:13AD 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 ...
* 1: 00000000:15B3 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 ...
* 2: 0F02000A:15B3 0202000A:CE8A 01 00000000:00000000 00:00000000 00000000 0 ...
*
*/
File procFile = new File(procFilePath);
Scanner scanner = null;
try {
scanner = new Scanner(procFile);
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
// Skip column headers
if (line.startsWith("sl")) {
continue;
}
String[] fields = line.split("\\s+");
final int expectedNumColumns = 12;
assertTrue(procFilePath + " should have at least " + expectedNumColumns
+ " columns of output " + fields, fields.length >= expectedNumColumns);
String localAddress = fields[1];
String state = fields[3];
assertTrue(procFilePath + " should have an IP address in the second column",
isAddress(localAddress));
if (!isException(localAddress) && isPortListening(state, isTcp)) {
throw new ListeningPortsAssertionError(
"Found port listening on " + localAddress + " in " + procFilePath);
}
}
} catch (FileNotFoundException notFound) {
fail("Could not open file " + procFilePath + " to check for listening ports.");
} finally {
if (scanner != null) {
scanner.close();
}
}
}
private static boolean isAddress(String localAddress) {
return isPatternMatch(ADDRESS_PATTERNS, localAddress);
}
private static boolean isException(String localAddress) {
return isPatternMatch(EXCEPTION_PATTERNS, localAddress);
}
private static boolean isPatternMatch(List<String> patterns, String input) {
for (String pattern : patterns) {
if (Pattern.matches(pattern, input)) {
return true;
}
}
return false;
}
private static boolean isPortListening(String state, boolean isTcp) {
// 0A = TCP_LISTEN from include/net/tcp_states.h
String listeningState = isTcp ? "0A" : "07";
return listeningState.equals(state);
}
private static class ListeningPortsAssertionError extends AssertionFailedError {
private ListeningPortsAssertionError(String msg) {
super(msg);
}
}
}

Bluetooth Detection Problems in Samsung Galaxy Tab using Android Bluetooth API

I have a problem detecting zero class bluetooth devices with my Galaxy Tab using the Android Bluetooth API. It simply does not "see" some devices although I can detect them with my phone or computer. Has anyone run into this problem? I´m writing an app which depends on pairing with a device through bluetooth and some help in this regard would be most appreciated.
Note: This solution will only work with old Android OSs, due to it's need for access to the device logs.
Yes! I have exactly the same problem, abeit on a Samsung Galaxy S, and LG Optimus One. I wrote a class you can reuse to fix this, no idea if it will work on the Galaxy Tab, but you can try:
package com.yourpackagename;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.AsyncTask;
// This class exists due to a bug in the Broadcomm bluetooth stack, which is
// used by many Android smart-phone manufacturers (LG, Samsung HTC etc.). That
// bug prevents discovery of ALL bluetooth devices that report their Class of Device (CoD)
// code as 0x00, which prevent many SPP (Serial Port Profile) devices from working.
//
// See: http://www.google.com/codesearch/p?hl=en#4hzE-Xyu5Wo/vendor/brcm/adaptation/dtun/dtunc_bz4/dtun_hcid.c&q=%22Device%20[%25s]%20class%20is%200x00%20-%20skip%20it.%22&sa=N&cd=1&ct=rc
// And: http://stackoverflow.com/questions/4215398/bluetooth-device-not-discoverable
// And: http://www.reddit.com/r/Android/comments/hao6p/my_experience_with_htc_support_eu_anyone_has/
//
// How to use (from your Activity class):
//
// (new BluetoothClassZeroDiscoveryTask(this, new BluetoothDiscoveryCallback())).execute();
//
// Where BluetoothDiscoveryCallback is a class defined e.g. in your Activity. The call method
// will be called after the discovery task completes, and is passed the complete list
// of paired bluetooth devices, including those that are undiscoverable due to the above bug.
//
// private class BluetoothDiscoveryCallback implements Action<ArrayList<BluetoothDevice>>
// {
// public void call(ArrayList<BluetoothDevice> devices)
// {
// // Now you have the list of ALL available devices,
// // including those that report class 0x00.
// }
// }
//
// // Java equivalent of the built-in Action from C#.
// public interface Action<T>
// {
// void call(T target);
// }
//
public class BluetoothClassZeroDiscoveryTask extends AsyncTask<Void, Void, Void>
{
// This is the well-known ID for bluetooth serial port profile (SPP) devices.
public static final UUID BluetoothSerialUuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private Activity _parent;
private boolean _discoveryComplete = false;
private Action<ArrayList<BluetoothDevice>> _callback;
private ArrayList<BluetoothDevice> _devices = new ArrayList<BluetoothDevice>();
private Calendar _discoveryStartTime;
private SimpleDateFormat _logDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
private BluetoothAdapter _adapter;
private ProgressDialog _progressDialog;
public BluetoothClassZeroDiscoveryTask(Activity parent, Action<ArrayList<BluetoothDevice>> callback)
{
_callback = callback;
_parent = parent;
_adapter = BluetoothAdapter.getDefaultAdapter();
IntentFilter foundFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
_parent.registerReceiver(mReceiver, foundFilter);
IntentFilter finishedFilter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
_parent.registerReceiver(mReceiver, finishedFilter);
// This task performs a scan for bluetooth devices, which
// takes ~ 12 seconds, so show an indeterminate progress bar.
_progressDialog = ProgressDialog.show(_parent, "", "Discovering bluetooth devices...", true);
}
// Kicks off bluetooth discovery.
#Override
protected Void doInBackground(Void... params)
{
_discoveryStartTime = Calendar.getInstance();
_adapter.startDiscovery();
while (!_discoveryComplete)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException e) { }
}
_adapter.cancelDiscovery();
return null;
}
// Provide notification of results to client.
#Override
protected void onPostExecute(Void result)
{
_progressDialog.dismiss();
_parent.unregisterReceiver(mReceiver);
_callback.call(_devices);
}
// Handler for bluetooth discovery events.
private final BroadcastReceiver mReceiver = new BroadcastReceiver()
{
#Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
{
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// If it's already paired, skip it, (we'll add it after the scan completes).
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
{
_devices.add(device);
}
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{
// Add all already-paired devices to the list.
for (BluetoothDevice device : _adapter.getBondedDevices())
{
_devices.add(device);
}
// Trawl through the logs to find any devices that were skipped >:(
try
{
Process process = Runtime.getRuntime().exec("logcat -d -v time *:E");
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
String line;
Pattern pattern = Pattern.compile("(.{18}).*\\[(.+)\\] class is 0x00 - skip it.");
while ((line = bufferedReader.readLine()) != null)
{
Matcher matcher = pattern.matcher(line);
if (matcher.find())
{
// Found a blocked device, check if it was newly discovered.
// Android log timestamps don't contain the year!?
String logTimeStamp = Integer.toString(_discoveryStartTime.get(Calendar.YEAR)) + "-" + matcher.group(1);
Date logTime = null;
try
{
logTime = _logDateFormat.parse(logTimeStamp);
}
catch (ParseException e) { }
if (logTime != null)
{
if (logTime.after(_discoveryStartTime.getTime()))
{
// Device was discovered during this scan,
// now we want to get the name of the device.
String deviceAddress = matcher.group(2);
BluetoothDevice device = _adapter.getRemoteDevice(deviceAddress);
// In order to get the name, we must attempt to connect to the device.
// This will attempt to pair with the device, and will ask the user
// for a PIN code if one is required.
try
{
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(BluetoothSerialUuid);
socket.connect();
socket.close();
_devices.add(device);
}
catch (IOException e) { }
}
}
}
}
}
catch (IOException e) {}
_discoveryComplete = true;
}
}
};
}
See also:
http://zornsoftware.codenature.info/blog/pairing-spp-bluetooth-devices-with-android-phones.html

Categories

Resources