I am recently working on a project that requires sending a command from my android mobile app to the android things on my raspberry pi 3. How can I achieve this through a WiFi connection?
I only need to send a String to the device.
If one of your devices isn't connected to internet, you could :
Option 1 :
use Google Nearby Connections API , the API choose the best way to communicate (eg: Bluetooth, Wifi...).
See https://github.com/googlesamples/android-nearby/tree/master/connections
Option 2 :
Use Socket to communicate but your devices need to be on the same network. If they aren't connected to the same network, you can connect them using WIFI P2P.
Using Android Things, you can use the Nearby Messages API, which gives you the ability to communicate to and transfer messages between two Android devices within their apps. Here's a code snippet:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mMessageListener = new MessageListener() {
#Override
public void onFound(Message message) {
Log.d(TAG, "Found message: " + new String(message.getContent()));
}
#Override
public void onLost(Message message) {
Log.d(TAG, "Lost sight of message: " + new String(message.getContent()));
}
}
mMessage = new Message("Hello World".getBytes());
}
#Override
public void onStart() {
super.onStart();
...
Nearby.getMessagesClient(this).publish(mMessage);
Nearby.getMessagesClient(this).subscribe(mMessageListener);
}
#Override
public void onStop() {
Nearby.getMessagesClient(this).unpublish(mMessage);
Nearby.getMessagesClient(this).unsubscribe(mMessageListener);
...
super.onStop();
}
If you use system like Raspbian you can transform your Raspberry into a server.Then, You will have different ways to send your command:
Option 1: Set up an Http server on your raspberry (PHP, NodeJS, JEE, ...) and send command via HTTP Request.
Option 2: Set up a Socket Server on your raspberry (Socket.io, raw socket, ...) and send command via socket client
Option 3 Set up MQTT Server on your raspberry and send command via MQTT client (this last option is the way to go when talking about Internet of Things). Note that the program which receive command should implement MQTT Client as MQTT is based on pub/sub pattern.
You can use nanoHttpd on Android things and other library such as retrofit or volley on the Android device.
Check out this example for controlling a car via an Http API: https://github.com/plattysoft/IotCar
Related
I want to connect to my localhost server for testing my app. For this reason, I am using the retrofit library. This is my interface class, which defines the url to connect to:
import retrofit2.Call;
import retrofit2.http.Field;
import retrofit2.http.FormUrlEncoded;
import retrofit2.http.POST;
public interface PostInterface {
String JSONURL = "http://80.0.0.13/";
#FormUrlEncoded
#POST("login_screen/backend.php")
Call<String> getUserLogin(
#Field("input") String input,
#Field("username") String uname,
#Field("password") String password
);
}
I am calling this interface in my java code:
Call<String> call = null;
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(PostInterface.JSONURL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
PostInterface api = retrofit.create(PostInterface.class);
call = api.getUserLogin("sign in", "abc", "abc#xyz");
if (call != null) {
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if (response.body() != null) {
Log.d("success",response.body());
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), t.toString(), Snackbar.LENGTH_SHORT);
snackbar.show();
}
});
}
Strangely, the onFailure() method keeps triggering everytime with the following throwable:
javaSocketTimeoutException: Failed to connect to /80.0.0.13 (port 80)....
But when I try the url in my android browser or pc browser, it works fine.
Things I have checked:
The project is stored inside C:\xampp\htdocs, having the exact same hierarchy as in my live server location.
Both Apache and SQL ports are open in my xampp control panel.
My localhost port number is default 80
When I run the app in my emulator using this ip http://10.0.2.2:80/, then it works fine
Why is the app failing to connect to my local server?
EDIT: I can access my site from my phone browser using my pc ip address, but when I want to access it from the app, then the onFailure() triggers
After much struggling, I finally found the solution from a post in github:
Turn on USB Tethering & USB Debugging Mode in your mobile.
Connect your mobile to your laptop/desktop through USB.
Now just change the ip address (run "ipconfig" in cmd)
This is because localhost is not a valid URL for android.
The localhost is a loopback address, which means that the network request will be handled by current device by some application (PHP server).
So, when you enter localhost on your machine (PC/laptop), it will check for server application listening at specified port (in your case 80) and will forward that request to the server application. In your case it is XAMPP which is listening at port 80.
But, when you goto an Android application, there is no server application running on android device or emulator since they are different device. Hence you get 404 error for localhost on Android.
To fix this, simply get the IP address of your PC (using ipconfig command) and use that instead of localhost.
E.g.: In cas the IP address is 192.168.0.129, then your URL would be http://192.168.0.129:80/
I have a wear-os standalone application written in java, which connects as client (org.java_websocket.client.WebSocketClient) via WLAN websockets to a server (org.java_websocket.server.WebSocketServer) running on the smartphone (TicWatch Pro 3). When I run the code, everything works fine (web sockets connect) as long as the smartwatch is charging. As soon as I disconnect the charger and try to connect the smartwatch client via websockets to the smartphone server no connection can be established. No error is shown, there is simply no connection established.
This is a simplified version of the Runnable class used to start the web socket client.
public class BackgroundReceiverThread implements Runnable {
public static void startBackgroundReceiver(){
AsyncTask.execute(new BackgroundReceiverThread());
}
private BackgroundReceiverThread() {}
//#Override
public void run() {
try {
client=new BackgroundReceiverClient(new URI("ws://localhost:8887"));
client.connect();
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
}
The BackgroundReceiverClient class looks the following:
public class BackgroundReceiverClient extends WebSocketClient {
public BackgroundReceiverClient(URI serverUri) {
super(serverUri);
}
#Override
public void onOpen(ServerHandshake serverHandshake) {
Log.i("mytag","On Open");
}
#Override
public void onError(Exception e) {
Log.i("mytag","On Error:"+e.getMessage());
}
}
When the smartwatch is charging and BackgroundReceiverThread.startBackgroundReceiver() is invoked, the onOpen() method is invoked. When the charger is disconnected the onOpen() method is not invoked.
I assume this is due to energy saving precautions of the smartwatch, which are activated when not charging. I have already tried to identify the respective setting on the smartwatch but couldn't find it.
How can I get the client connecting to the server when the smartwatch is not charging?
I had a fairly similar problem, I was trying to connect via Socket.IO with my Ticwatch E2 and it only worked when charging. After searching for all kinds of energy saving precautions that I could disable the real problem after all was this:
My Ticwatch automatically connects with my phone via Bluetooth and uses the wi-fi my phone is connected to through my phone (You can see the connection status in the Wear OS app on your phone). In order to establish a Socket Connection, the watch needs to be connected to the wi-fi itself. It does not do that by default when connected to your phone.
You can easily test this hypothesis by enabling flight mode on your phone and try the application on your Ticwatch again, it worked for my socket.IO application.
I'm currently developping my first app in java.
This app requires a direct connection with my BL652, which doesn' t accept any kind of pairing option. That being said, I'm stuck with the code below, which still tries to pair with my bluetooth device instead of just connecting. Therefore, I wanted to know what am i supposed to do in order to make a connection that doesnt require pairing.
Thanks in advance for any response.
String mac_address = "DA:72:21:29:0F:F0";
private static final UUID MY_UUID = UUID.fromString("E54B0002-67F5-479E-8711-B3B99198CE6C");
lvNewDevices.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
BluetoothDevice device = (BluetoothDevice) mBluetoothAdapter.getRemoteDevice(mac_address);
try {
socket = device.createInsecureRfcommSocketToServiceRecord(MY_UUID);
socket.connect();
} catch (IOException e) {
e.printStackTrace();
}
I'm not sure about connection to external hardware but it's definetly possible to connect 2 phones without pairing. I made it using Android Nearby Connections . And yeah it's basically working with BLE. As far as I know it's possible to connect to RaspberryPi using that API.
Bluetooth devices can be made to communicate with each other using master-slave configuration. I first tried with two BLE-HC05s, made one as master and the other as slave, and as expected the master is able to send data, slave is able to receive data, that can be seen using the Serial Monitor in Arduino IDE. I have developed a similar app, which connects to a BLE-HC05 device, sends and receives data. But since you are trying to get data or send data to the App on your phone, Android will not support such unpaired anonymous communications. If you are having trouble with connection or pairing Bluetooth device and your app, I may help you with that. But as far as Bluetooth communication without pairing is concerned, you may not be able to find a way.
Edit: The code to connect any bluetooth device, like BLE-HC06 as you have mentioned, is 1234 (Only if you have not changed it)
I am new to bluetooth programming, so please keep that in mind.
I am trying to connect to a pulse sensor from a desktop pc, specifically the Zephyr HxM BT. I am not using any device specific drivers, the Java bluetooth library I'm using is Bluecove, and my bluetooth stack is BlueSoleil.
From my understanding, the way I proceed is
1) Scan for BT devices
public void startSearch() throws BluetoothStateException{
System.out.println("Inquiry started");
localdevice.getDiscoveryAgent().startInquiry(DiscoveryAgent.GIAC, this);
}
This works fine, it discovers my pulse belt and calls
public void deviceDiscovered(RemoteDevice arg0, DeviceClass arg1)
2) Search a device for services
Once a device has been discovered, it should be added to the DiscoveryAgent's list of cached devices, this is my first problem as the cache (and preknown devices) is always empty even though I've discovered my belt.
So the way that I do this now is to either keep my own list of devices, or simply start a service search directly from deviceDiscovered.
I am still a bit unsure if I'm using the correct parameters, but from reading the BT device manual and the javax.bluetooth documentation on DiscoveryAgent.searchServices:
public int searchServices(int[] attrSet,
UUID[] uuidSet,
RemoteDevice btDev,
DiscoveryListener discListener)
throws BluetoothStateException
My code:
public void searchServices(RemoteDevice device){
UUID[] uuidSet = new UUID[1];
uuidSet[0]=new UUID("1101",false); //Serial Port
System.out.println("Searching for services on " + device.getBluetoothAddress() );
try{
agent.searchServices(null,uuidSet, device,this);}
catch (BluetoothStateException e){
System.out.println("BluetoothStateException caught.");
}
}
I've set the attributes parameter to null, because the documentation states that this will have it search for services with the default attributes, however I've also tried to use only ServiceID (0x0003) as attribute with no luck.
This is where I'm stuck, I pass the correct BT device into the function, and it starts searching but never give me any results, it just searches forever for all I know, no exception, no calls to
public void servicesDiscovered(int arg0, ServiceRecord[] arg1)
or
public void serviceSearchCompleted(int arg0, int arg1)
So I guess my questions are:
- Am I doing something wrong? Any suggestions?
- What are the other approaches to connecting to a BT device, and what
information do I have to know about the device to do that?
Here is some information that I think is relevant from the device manual:
The following steps have to be undertaken to connect to a HxM device.
1) Activate the Bluetooth service of the device/computer wanting to connect to the HxM
2) Scan for Bluetooth devices in range
3) Pair with the HxM device found in range
4) Discover Services of Paired HxM
5) Connect to serial port of HxM device
The diagram above shows that the Bluetooth HxM typically communicates with a mobile device over the Bluetooth
link. The HxM only supports one link at a time and uses the Bluetooth SPP (Serial Port Profile) to communicate
with other devices with the following low-level protocol:
• 115,200 baud
• 8 data bits
• 1 stop bit
• No parity
Any suggestions are very much appreciated
edit: I just want to add that I'm testing the code with a console input loop, so the program is not immediately terminated after calling searchServices, it should have time to complete unless I'm misunderstanding async tasks
I just wanted to update this and say that I found the problem, it seems that I had to use a short UUID instead of a long. I should have tried both of these options before I deemed myself stuck, but I didn't think it would make any difference.
I'm working on Android game which is turn based, and I've chosen Nodejs for the server side. I've been exploring for about two weeks how to communicate from the Android client side to the Nodejs server. Is there any way to communicate between the two.
Kindly help me if any one have any experience with such a project.
There are lots of options for something like this depending on what your game requires for communicating between client and server. For instance looking up "TCP clients for android" here shows up answers like this. If fast updates are important between server and client then UDP is one option, if your game can cope with the loss of some packets in the middle.
Besides TCP/UDP you also have things like WebSockets for Android.
Combining Android & nodejs is no problem. First you have to define a middelware. You can use REST-Webservices or any other technology for the communication between the node server and the android client. There are many standard APIs and protocols. I would use Websocket for the communication. You can find Android / Node.js APIs with WebSocket support here:
http://cjihrig.com/blog/creating-your-own-node-js-websocket-echo-server/
https://github.com/Worlize/WebSocket-Node
http://jwebsocket.org/mobile/android/android_part1.htm
http://code.google.com/p/weberknecht/
You can use Volley in Android to make a json POST or GET request.
And for the NODE JS you can use node's built-in http module to create a simple HTTP server and then receive data from the req object.
const http=require('http');
const stringDecoder=require('string_decoder').StringDecoder;
var httpServer=http.createServer(function(req,res){
unifinedServer(req,res);
});
//Just another method.
var unifinedServer=function(req,res){
var decoder=new stringDecoder('utf-8');
var buffer='';
//reading the post data.
req.on('data',function(data){
buffer+=decoder.write(data);
});
//Reading of data is completed.
req.on('end',function(){
buffer+=decoder.end();
// Do what ever you want to do with the POST data.
});
}
//The Server is listening on a specific port.
httpServer.listen(7000,function(){
console.log("Server is now listening on Port..."+7000);
});
For the Android Code you can do this with volley:
String url = "http://example.com";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.POST, url, postJsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
mTextView.setText("Response: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
}
});
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);