I am attempting to communicate with a Pi header using Android Things Developer Preview 5. Below is the class I have created to communicate with the header as per the official Android Things documentation:
public class UartComm {
private static final String UART_DEVICE_NAME = "UART1";
private UartDevice mDevice;
private void configureUartFrame(UartDevice uart) throws IOException {
// Configure the UART port
uart.setBaudrate(115200);
}
public void onCreate() {
try {
PeripheralManagerService manager = new PeripheralManagerService();
List<String> deviceList = manager.getUartDeviceList();
if (deviceList.isEmpty()) {
Log.i(TAG, "No UART port available on this device.");
} else {
Log.i(TAG, "List of available devices: " + deviceList);
}
mDevice = manager.openUartDevice(UART_DEVICE_NAME);
configureUartFrame(mDevice);
mDevice.registerUartDeviceCallback(mUartCallback);
} catch (Exception e) {
Log.w(TAG, "Unable to access UART device", e);
}
}
public void readUartBuffer(UartDevice uart) throws IOException {
// Maximum amount of data to read at one time
final int maxCount = 40;
byte[] buffer = new byte[maxCount];
uart.read(buffer, maxCount);
String data = new String(buffer, "UTF-8");
Log.d(TAG, data);
}
private UartDeviceCallback mUartCallback = new UartDeviceCallback() {
#Override
public boolean onUartDeviceDataAvailable(UartDevice uart) {
// Read available data from the UART device
try {
readUartBuffer(uart);
} catch (IOException e) {
Log.w(TAG, "Unable to access UART device", e);
}
// Continue listening for more interrupts
return true;
}
#Override
public void onUartDeviceError(UartDevice uart, int error) {
Log.w(TAG, uart + ": Error event " + error);
}
};
}
In my MainActivity I create an instance of UartComm by doing UartComm device = new UartComm() and the proceed to call device.onCreate()
I have also modified /boot/cmdline.txt and removed the console=serial0,115200 and replaced it with console=tty0, I have also tried just removing the console line without adding console=tty0. In /boot/config.txt I have also removed enable_uart=1 and core-freq=400 and also added dtoverlay=pi3-miniuart-bt I have also tried to remove Bluetooth support altogether by doing dtoverlay=pi3-disable-bt to no avail.
I have tested that the header works and is configured correctly in Rapsbian, where I swapped /dev/ttyAMA0 and /dev/ttyS0 and it worked correctly. I was able to run the screen command on Raspbian with a default baud rate of 115200 and was able to get the desired information.
I would like to do the same in Android Things Developer Preview 5 and have the Bluetooth run over the mini-uart ttyS0 and the header run over ttyAMA0. My desired result is for the header to be accessible over UART0.
An older USB serial device that has the same functionality works, but I would prefer the UART device be physically on top of the Pi, so that is not an option.
Might be wrong but shouldn't:
private static final String UART_DEVICE_NAME = "UART1";
be UART0 i.e.
private static final String UART_DEVICE_NAME = "UART0";
I did a UART example here https://github.com/blundell/androidthings-uart/blob/master/app/src/main/java/com/blundell/tut/MainActivity.java (obviously different hardware) But it's connected to raspberry pi pins in the same way like so:
Related
Let me quickly describe my setup and goal. I have a android tablet display running Android version 7.1.2
I have a motor controller that is hooked up to the Android tablet via ethernet. In my Android app that controls the motor controller, I use Wifi to communicate with some servers that provide/store data. Currently, I can use an Android simulator (in Android Studio) that allows me to communicate with the motor controller while also using the wifi for calls to the server. When I run the app on the Android tablet itself, I can only have Wifi OR Ethernet active at one time.
According to this post this is a hard limitation in Android itself. It also details some possible fixes, but its quite old and to be honest I do not have any experience in the required steps described by their vague instructions.
Can anyone provide a more up-to-date solution to this problem, preferably one that is a little more detailed for newbies like me? Even just a pointer to learning how to do the necessary steps for fixing this would be great, I've been stuck on this for awhile! Thanks for any help!
EDIT: Here's some relevant info in regards to AlwaysLearning's answer...
The class I use to manage reading from Modbus
public class ModbusRead {
private static final String TAG = "MODBUS READ";
ModbusClient mClientReadAll;
public ModbusRead()
{
// IP = "192.168.124.2";
// port = 502;
mClientReadAll = new ModbusClient(Modbus.IP, Integer.valueOf(Modbus.port));
mClientReadAll.setUnitIdentifier((byte)255);
}
public Runnable readAll()
{
return () -> {
ReadAllFromModbus mReadAll = new ReadAllFromModbus();
mReadAll.execute();
};
}
public class ReadAllFromModbus extends AsyncTask<String, Void, String> {
private final String TAG = "READ ALL FROM MODBUS";
#Override
protected String doInBackground(String... params) {
try
{
mClientReadAll.Connect();
// get all registers
int[] registerBlock = mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_MODE.getRegister()- 1, 16);
int[] wideRegisters = new int[] {
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ACTUAL_POSITION.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_TARGET_POSITION.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ROM_DELTA.getRegister() - 1, 2)),
Modbus.convertWideRegister(mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_REWIND_ZERO.getRegister() - 1, 2))
};
int[] tensionRegister = mClientReadAll.ReadHoldingRegisters(Constants.RegisterRead.HR_ACTUAL_TENSION.getRegister() - 1, 1);
Modbus.updateAllRegisters(registerBlock, wideRegisters, tensionRegister);
}
catch (Exception e)
{
Log.i(TAG, "ERROR IN GETTING ALL REGISTERS LOOP: " + e.getMessage());
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
try
{
mClientReadAll.Disconnect();
}
catch(Exception e)
{
Log.i(TAG, "ERROR IN DISCONNECTING");
}
}
}
}
The relevant part of my Dashboard class that would handle starting the thread that does all the modbus reading
How would I go about forcing the ModbusRead class to use the Ethernet here?
ModbusRead modbusRead = new ModbusRead();
final ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
final NetworkRequest requestEthernet = new NetworkRequest.Builder()
.addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
.build();
final ConnectivityManager.NetworkCallback cbEthernet = new ConnectivityManager.NetworkCallback() {
#Override
public void onAvailable(Network network) {
// connectivityManager.bindProcessToNetwork(network);
try
{
// Modbus.IP = "192.168.124.2"
// Modbus.port = 502
Log.i(TAG, "TRYING TO BIND SOCKET...");
InetAddress address = InetAddress.getByName(Modbus.IP);
Log.i(TAG, "ADDRESS: " + address.toString());
Socket socket = new Socket(address, Modbus.port);
Log.i(TAG, "SOCKET CREATED..." + socket.getInetAddress());
network.bindSocket(socket);
Log.i(TAG, "BOUND ETHERNET");
}
catch (Exception e)
{
e.printStackTrace();
Log.i(TAG, "EXCEPTION: " + e.getMessage());
}
}
};
connectivityManager.requestNetwork(requestEthernet, cbEthernet);
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
executorService.scheduleAtFixedRate(modbusRead.readAll(), 2000, 250, TimeUnit.MILLISECONDS);
I'm new to Android Studio and I'm using the functionality of Local Only Hotspot to turn on and off programmatically the hotspot (found this two post for reference: How to turn on/off wifi hotspot programmatically in Android 8.0 (Oreo),How to turn on Wifi-Hotspot programmatically on Android >= 7.1 (including sharing the internet access)? .
private void turnOnHotspot() {
wifiManager.startLocalOnlyHotspot(new
WifiManager.LocalOnlyHotspotCallback()
{
#Override
public void onStarted(WifiManager.LocalOnlyHotspotReservation reservation) {
super.onStarted(reservation);
hotspotReservation = reservation;
String key = hotspotReservation.getWifiConfiguration().preSharedKey;
String ussid = hotspotReservation.getWifiConfiguration().SSID;
System.out.println("KEY: "+ key);
System.out.println("USSID: "+ ussid);
currentConfig = hotspotReservation.getWifiConfiguration();
System.out.println("STARTED THE HOTSPOT");
}
#Override
public void onStopped() {
super.onStopped();
System.out.println("STOPPED THE HOTSPOT");
}
#Override
public void onFailed(int reason) {
super.onFailed(reason);
System.out.println("FAILED THE HOTSPOT");
}
}, new Handler());
}
private void turnOffHotspot() {
active = false;
if (hotspotReservation != null) {
hotspotReservation.close();
System.out.println("CLOSE HOTSPOT");
}
}
But from what I gather from other older posts and documentation, this method gives a local network without internet access and a random SSID and Password that cannot be personalised.
I need to connect only one device to this hotspot to share the mobile data (to have internet access), but I didn't find anything that could have help me. Is there another alternative?
I am able to pair devices with the android studio app but I get the tag
"CouldNotConnectToSocket" even though the device is paired.
I am new to android studio so I am really stuck with where to go next.
I also get
getBluetoothService() called with no BluetoothManagerCallback
The UUID I created is:
private final static UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Can anyone please help me?
new Thread() {
#Override
public void run() {
device = BA.getRemoteDevice(address);
try {
BTSocket = device.createRfcommSocketToServiceRecord(BTMODULEUUID);
//BTSocket = createBluetoothSocket(device);
Log.d(TAG, "Device Connected");
BA.cancelDiscovery();
BTSocket.connect();
} catch (IOException ex) {
Log.d(TAG, "CouldNotConnectToSocket");
closeSocket(BTSocket);
}
}
}.start();
The issue I found out was that the devices I was trying to connect to send data back and forth require Bluetooth Low Energy support from the app.
I have been stuck with one problem. I need some people which check a part of my code and help me with problem and critize my code (I write code but I haven't people which can say this is wrong or something in this pattern)
Generally.
My service get message from bluetooth (HC-05) and I can see values in Log.d, in service.
A part code of my service which get message.
private class ConnectedThread extends Thread{
private final BluetoothSocket bluetoothSocket;
private final InputStream inputStream;
private final OutputStream outputStream;
public ConnectedThread(BluetoothSocket socket){
Log.d(TAG,"ConnectedThread: Starting");
bluetoothSocket=socket;
InputStream tmpInput = null;
OutputStream tmpOutput = null;
try{
tmpInput = bluetoothSocket.getInputStream();
tmpOutput = bluetoothSocket.getOutputStream();
}catch (IOException e){
e.printStackTrace();
active=false;
}
inputStream=tmpInput;
outputStream=tmpOutput;
}
#Override
public void run() {
byte[] buffer = new byte[1024];
int bytes;
while(active){
try {
bytes = inputStream.read(buffer);
final String comingMsg = new String(buffer,0,bytes);
Log.d(TAG,"InputStream: " + comingMsg);
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
Message message = new Message();
message.obj = comingMsg;
message.what = 1; // I need it to prevent NullObjReference
Log.d(TAG,"Handler run(): " + message.obj);
mHandler.sendMessage(message);
}
});
}catch (IOException e){
Log.e(TAG,"Write: Error reading input." + e.getMessage());
active=false;
break;
}
}
}
...some code is hidden because it is diploma thesis
}
The problem is get message every time from this service to another activity where all is happen.
I tried a lot of things (with Threads,Looper,runOnUiThread, handleMessage and callback), checked a lot of posts in stackoverflow and I tried to combine with my project but all time I had nullobjectreference (for that i tried to use msg.what to check) , black screen when tried to move to my home activity (it is main) and update my textView or typical crash app.
Now I want only to get message from service to textview. When everything starts working fine, I want to parse string (for example 3 first chars) and send message to one of six textviews.
A part of codes from onCreate before method runThread() is started:
Log.d(TAG,"Check intent - result");
if(getIntent().getIntExtra("result",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded device");
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service ");
checkIfActive();;
}
Log.d(TAG,"Check intent - connect_to_paired");
if(getIntent().getIntExtra("connect_to_paired",0)==RESULT_OK){
mDevice = getIntent().getExtras().getParcelable("bonded_paired_device");
startConnection(mDevice,MY_UUID);
Log.d(TAG,"Check is active service ");
checkIfActive();
}
public void checkIfActive(){
Log.d(TAG,"CheckIfActive: Started");
while(myBluetoothService.active!=true) {
Log.d(TAG,"CheckIfActive() active is "+ myBluetoothService.active);
if (myBluetoothService.active) {
Log.d(TAG, "CheckIfActive: Running method runOnUiThread - myBluetoothService.active is "+myBluetoothService.active);
runThread();
}
}
}
Method runThread() which should work everytime after connected with bluetooth device:
public void runThread(){
//I used there Thread but when connection was fail,
// method created multiply threads when I tried to connect next time
runOnUiThread(new Runnable() {
#Override
public void run() {
handler = new Handler(Looper.getMainLooper()){
#Override
public void handleMessage(Message msg) {
while (true) {
switch (msg.what) {
//when is one, service has messages to send
case 1:
String message = myBluetoothService.mHandler.obtainMessage().toString();
rearLeft.setText(message);
break;
default:
super.handleMessage(msg);
}
}
}
};
}
});
}
UPDATE:
Is it good idea ? Maybe I can put JSON Object to service to send message and in the HomeActivity, I can try get values from JSON. Is it fast ? I send a lot of data, because bluetooth receive data of distance from 4 ultrasound sensors in 4 times in lasts until few milliseconds, everytime.
Here is screen how sees my data in service when I have debug logs.
Next idea, but still nothing:
HomeActivity (my main)
public void runThread(){
runOnUiThread(new Runnable() {
#Override
public void run() {
//Looper.prepare();
new Handler() {
#Override
public void handleMessage(Message msg) {
rearLeft.setText(msg.obj.toString());
}
};
//Looper.loop();
//Log.d(TAG, myBluetoothService.mHandler.getLooper().toString());
//rearLeft.setText(myBluetoothService.mHandler.getLooper().toString());
}
});
}
Service which should send data from bluetooth to UI Thread is the same (Check first code).
Screen from HomeActivity where you can see 6 text views. Now I want put all text to one view which will be refresh by get next message.
Ok this post a bit help me to solve problem:
Sending a simple message from Service to Activity
Maybe this link could help another people.
Thanks for help, now understand why i should use broadcast receiver to do this.
I've been running into a problem using the AWS Mobile SDK version 2.2.15. After carefully looking at their own S3TransferUtilitySample, I have made a couple attempts to get a file uploaded to an Amazon S3 bucket on my own.
My first attempt was to try calling the TransferUtility's .upload() method from within Android's own AsyncTask, inside the doInBackground() method. No success there, and after reading about this issue, it inspired me to try moving the SDK calls outside of the AsyncTask and into the UI thread under onPostExecute() in suspicion that the call itself is asynchronous and the AsyncTask is running garbage collection on the AWS SDK objects. Still no luck, no exceptions are being thrown, and no indication of anything going wrong aside from the file not actually uploading.
My second attempt was following this exact example. I downloaded the source and was able to supply the application with the correct identity pool ID, region, bucket, key, and a test jpeg file. I ran the application and the calls were being made. The file made it to AWS S3 without any issues.
I copied their exact methods into a helper class of my application, and made all the AWS SDK objects a static field of the class, but I am still running into the same issue of no exceptions being thrown. I ended up making the fields non-static and instantiating the helper class as an object in my main activity, safely assuming that the object would not be treated with garbage collection. Still nothing! No indication of failure from these calls!
I decided to get really generous with logging using Android's Log.i() method, watching every step of the way, and it even makes it to the TransferUtility's .upload() method, but even having the TransferListener set and full of logging lines, there is no status change, onError() is not being called. TransferUtility's .upload() and its resulting TransferObserver object is not reporting anything like it was running the test application.
Here are a couple things to note:
* The correct identity pool ID is being used here, no issue with that
* I have tried using both version 2.2.15 as well as 2.2.13
* All dependencies included are .jar files, the project is not Gradle (yet)
* The service is declared in the manifest just as it was in the examples
* There are no build errors, Android Studio builds the project just fine
* The TransferListener object is not firing onStateChanged(), onProgressChanged(), nor onError()
Has anyone encountered such a strange issue with AWS S3 SDK? Any suggestions on how I can better debug this issue?
Here's the class right now:
public class AmazonS3Helper
{
Context context;
public String bucket;
public String key;
public File file;
public AmazonS3 s3;
public TransferUtility utility;
public AmazonS3Helper(JSONObject p, Context c)
{
Log.i("tag", "new AmazonS3Helper object");
this.context = c;
try
{
bucket = p.getString("bucket");
key = p.getString("key");
this.file = new File(
c.getExternalFilesDir(null),
"nn_temp_photo.jpg");
credentialsProvider();
setTransferUtility();
upload();
}
catch (Exception x)
{
Log.i("tag", "Error in new AmazonS3Helper object: " + x.getMessage());
}
}
public void credentialsProvider()
{
Log.i("tag", "Providing credentials");
try
{
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
this.context,
// This has been verified to return the correct identity pool
MyApplicationClass.getPreference("aws.credentials"),
Regions.US_EAST_1);
setAmazonS3Client(credentialsProvider);
}
catch (Exception x)
{
Log.i("tag", "Error in providing credentials: " + x.getMessage());
}
}
public void setAmazonS3Client(CognitoCachingCredentialsProvider credentialsProvider)
{
Log.i("tag", "Setting amazon s3 client");
try
{
s3 = new AmazonS3Client(credentialsProvider);
s3.setRegion(Region.getRegion(Regions.US_EAST_1));
}
catch (Exception x)
{
Log.i("tag", "Error in setting amazon s3 client:" + x.getMessage());
}
}
public void setTransferUtility()
{
Log.i("tag", "Setting transfer utility");
try
{
utility =
new TransferUtility(
s3,
this.context);
}
catch (Exception x)
{
Log.i("tag", "Error in setting transfer utility: " + x.getMessage());
}
}
public void upload()
{
Log.i("tag", "uploading");
try
{
TransferObserver transferObserver = utility.upload(
bucket,
key,
file
);
transferObserverListener(transferObserver);
}
catch (Exception x)
{
Log.i("tag", "Error in uploading: " + x.getMessage());
}
}
public void transferObserverListener(TransferObserver transferObserver)
{
Log.i("tag", "transferObserverListener");
try
{
transferObserver.setTransferListener(new TransferListener()
{
#Override
public void onStateChanged(int id, TransferState state)
{
Log.i("tag", state + "");
}
#Override
public void onProgressChanged(int id, long bytesCurrent, long bytesTotal)
{
int percentage = (int) (bytesCurrent / bytesTotal * 100);
Log.i("tag", percentage + "");
}
#Override
public void onError(int id, Exception ex)
{
Log.i("tag", "error");
}
});
}
catch (Exception x)
{
Log.i("tag", "Error in transferObserverListener: " + x.getMessage());
}
}
}
Edit
I forgot to mention, but the version of Android this is being tested on is Android Lollipop 5.1.
This is a bug in 2.2.15. Some IO exceptions aren't reported. It is fixed in 2.2.16. Would you please try the latest version?
The issue has been solved and is entirely unrelated to the code itself. What was happening was that I was declaring the com.amazonaws.mobileconnectors.s3.transferutility.TransferService in the library's manifest, but the child apps also needed it in their manifest.
I found this out by dropping the sample Activity straight into my application, and realizing the child apps also needed this activity declaration. The child apps have no code themselves, but without the declaration in their own manifest, they are unaware the activities/services being referenced exist. In this case, Amazon was silently refusing to upload because the service wasn't declared for the specific application.