I have a board that sends jsons with telemetry to Azure IoT hub (using http). I want to read telemetry data with my android device. I looked some examples of reading messages from IoT hub for android, but I found only how to read them from "Cloud to device feedback" endpoint. So now my application looks like:
Json from the board ----> "Events" endpoint ---> Function application that resending json to "Cloud to device feedback" endpoint
-----> "Cloud to device feedback" endpoint ----> Android device.
I'm a beginner in Azure, so I'm sure that exists smarter way to do that. (Json from the board ----> "Events" endpoint ---> Android device). I did it on my desktop, but looks like android doesn't work with some libraries from desktop project.
Does anybody know how can I do it? (maybe some guides or lessons)
Desktop version
Part of android code:
public void btnReceiveOnClick(View v) throws URISyntaxException, IOException
{
System.out.println("Receiving:");
Button button = (Button) v;
// Comment/uncomment from lines below to use HTTPS or MQTT protocol
//IotHubClientProtocol protocol = IotHubClientProtocol.HTTPS;
IotHubClientProtocol protocol = IotHubClientProtocol.MQTT;
DeviceClient client = new DeviceClient(connString, protocol);
if (protocol == IotHubClientProtocol.MQTT)
{
MessageCallbackMqtt callback = new MessageCallbackMqtt();
Counter counter = new Counter(0);
client.setMessageCallback(callback, counter);
} else
{
MessageCallback callback = new MessageCallback();
Counter counter = new Counter(0);
client.setMessageCallback(callback, counter);
}
try
{
client.open();
} catch (Exception e2)
{
System.out.println("Exception while opening IoTHub connection: " + e2.toString());
}
try
{
Thread.sleep(1000);
} catch (InterruptedException e)
{
e.printStackTrace();
}
client.closeNow();
try {
....
}catch (JSONException je){
....
}
}
// Our MQTT doesn't support abandon/reject, so we will only display the messaged received
// from IoTHub and return COMPLETE
static class MessageCallbackMqtt implements com.microsoft.azure.sdk.iot.device.MessageCallback
{
public IotHubMessageResult execute(Message msg, Object context)
{
responce = new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET);
Counter counter = (Counter) context;
System.out.println(
"[from MessageCallbackMqtt] Received message " + counter.toString()
+ " with content: " + responce);
counter.increment();
return IotHubMessageResult.COMPLETE;
}
}
static class EventCallback implements IotHubEventCallback
{
public void execute(IotHubStatusCode status, Object context)
{
Integer i = (Integer) context;
System.out.println("[from EventCallback] IoT Hub responded to message " + i.toString()
+ " with status " + status.name());
}
}
static class MessageCallback implements com.microsoft.azure.sdk.iot.device.MessageCallback
{
public IotHubMessageResult execute(Message msg, Object context)
{
Counter counter = (Counter) context;
System.out.println(
"Received message " + counter.toString()
+ " with content: " + new String(msg.getBytes(), Message.DEFAULT_IOTHUB_MESSAGE_CHARSET));
int switchVal = counter.get() % 3;
IotHubMessageResult res;
switch (switchVal)
{
case 0:
res = IotHubMessageResult.COMPLETE;
break;
case 1:
res = IotHubMessageResult.ABANDON;
break;
case 2:
res = IotHubMessageResult.REJECT;
break;
default:
// should never happen.
throw new IllegalStateException("Invalid message result specified.");
}
System.out.println("Responding to message " + counter.toString() + " with " + res.name());
counter.increment();
return res;
}
}
You can refer to this document.It shows how to read the telemetry from you IoT Hub with Java.In the ReadDeviceToCloudMessages.java sample, it connects to the service-side Events endpoint on your IoT Hub and receives the device-to-cloud messages.
BTW, you can get the eventHubsCompatibleEndpoint, eventHubsCompatiblePath and iotHubSasKey from Azure Portal simply. The eventHubsCompatibleEndpoint is in this format:
sb://xxxxxxxxxxxxxx.servicebus.windows.net/
Related
I have configured one xbee pro as coordinator (API mode) and other as router (API mode). I trying to send data from coordinator to router using xbee java api, but in the router code i keep getting null, am I doing something wrong.
Below is the code for Sending data (coordinator):
public class MainApp {
private static final String PORT = "/dev/ttyUSB0";
private static final int BAUDRATE = 9600;
public static void main(String[] args)
{
String data = "Helloww";
XBeeDevice mycord = new XBeeDevice(PORT, BAUDRATE);
try {
mycord.open();
System.out.println("Port is opened\n");
System.out.println("remote device connection\n");
//mac of my router
RemoteXBeeDevice router = new RemoteXBeeDevice(mycord,
new XBee64BitAddress("0013A20040DD9BDD"));
System.out.println("Sending data\n");
mycord.sendData(router, data.getBytes());
} catch (XBeeException e) {
e.printStackTrace();
mycord.close();
System.exit(1);
}
}
}
code on router side
public class RecvApp {
private static final String PORT = "/dev/ttyUSB1";
private static final int BAUDRATE = 9600;
public static void main(String[] args)
{
XBeeDevice myrouter = new XBeeDevice(PORT, BAUDRATE);
try {
myrouter.open();
System.out.println("router port opened\n");
//mac of coordinator
RemoteXBeeDevice remotecord = new RemoteXBeeDevice(myrouter, new XBee64BitAddress("0013A20040D96FE5"));
XBeeMessage msg = myrouter.readDataFrom(remotecord);
System.out.print(msg);
} catch (XBeeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
myrouter.close();
System.exit(1);
}
}
}
On the router you need to have a loop that checks for messages and prints them out. The API should have a method you can call to check for messages before calling readDataFrom() (or maybe you just ignore the null response). Sleep for a few milliseconds between each check. Right now, there isn't much opportunity for your message to come through before the program quits.
When debugging something like this, start by isolating your problem. Which side is failing, the coordinator or the router? Are you sure the XBee modules have joined to each other and are on the same network?
One test would be to run a simple terminal emulator on the serial port connected to the router, do you see any frames coming through? If you look at a hex dump of the bytes, do you see your "Helloww" message? If not, you need to get the coordinator working first before you debug your router.
Found the issue, I was not converting the message received in the correct format. Added the below lines
String content = HexUtils.prettyHexString(HexUtils.byteArrayToHexString(xbeeMessage.getData()));
System.out.println("Hex data" + "" + content + "\n");
String value = new String(xbeeMessage.getData());
System.out.print("Actual msg" + " " + value + "\n");
Works now :)
socket.on('sign_in', function(idA, idB) {
var idA = idA; //global vars
var idB = idB; //ignore this var
if (!clients[idA]) {
clients[idA] = socket.id;
}
console.log(idA + ' has connected');
io.to(clients[idA]).emit('sign_in', idA + ' has connected'); });
io.emit('sign_in', "user is signed in");
I am trying to emit the message,"'idA' has connected" to my android client. The problem is that the emitting to a specific client only works once. After it is called once the server stops sending the line "'idA' has connected". I have to reset my server in order to get it to work again, but the problem lingers. The basic io emit function consistently works which leads me to think its a problem with the specific client emit.
I have tried adding the option 'forceNew' to my socket connection but it does not change anything (I am using nkzawa socket-client).
my client code:
IO.Options options = new IO.Options();
options.forceNew = true;
socket = IO.socket(HOST, options);
and then using a new thread:
new Thread(new Runnable() {
#Override
public void run() {
Log.i(TAG, "attempting to connect socket");
socket.connect();
idA = "user1"
idB = "nicknameOfUser1"
socket.emit("sign_in", idA, idB);
}
}).start();
receiving the emit:
socket.on("sign_in", new Emitter.Listener() {
#Override
public void call(Object... args) {
String message = (String) args[0];
System.out.println(message);
}
});
Again, the message "'idA' has connected" will only print out the first time. But the message "user has signed in" is called consistently each time.
Turns out that my emit was written incorrectly.
io.to(clients[idA]).emit('sign_in', idA + ' has connected');
should be
clients[idA].emit('sign_in', idA + ' has connected');
also be sure to assign
clients[idA] = socket;
I have this code. I enter the project key from the Google console as the snederId and get an error:
service not available.
which steps would you recommend for me to double check in setting up the registration key?
private void registerInBackground() {
new AsyncTask<Void, Void, String>() {
#Override
protected String doInBackground(Void... params) {
String msg = "";
try {
if (gcm == null) {
gcm = GoogleCloudMessaging.getInstance(context);
}
regId = gcm.register(SENDER_ID);
msg = "Device registered, registration ID=" + regId;
// You should send the registration ID to your server over
// HTTP, so it
// can use GCM/HTTP or CCS to send messages to your app.
sendRegistrationIdToBackend();
saveRegIdToDb();
// For this demo: we don't need to send it because the
// device will send
// upstream messages to a server that echo back the message
// using the
// 'from' address in the message.
// Persist the regID - no need to register again.
storeRegistrationId(context, regId);
} catch (IOException ex) {
msg = "Error :" + ex.getMessage();
// If there is an error, don't just keep trying to register.
// Require the user to click a button again, or perform
// exponential back-off.
}
return msg;
}
#Override
protected void onPostExecute(String msg) {
// mDisplay.append(msg + "\n");
}
}.execute(null, null, null);
}
Some basic checks:
Was your project whitelisted by Google?
Do you use the correct sender_id (project number)?
Is network connection up?
Are Google Play Services installed and up to date?
One of the above checks should not be OK.
check sender id, it is project number
and turn on "APIs & auth" -> "Google Cloud Messaging for Android"
I'm using websockets to make a multiplayer game and I need to send multiple types of data across the server but when I connect to the server it's supposed to send back a name and number ("type") and ("data") respectively from the websocket library on connection. I don't need the type but ("data") is vital for the game logic to actually work.
Below is the code I have in my websockets onMessage() function:
#Override
public void onMessage(String message)
{
try
{
JSONObject json = new JSONObject(message);
if(json.has("type") && json.has("data"))
{
Log.d(TAG, json.getString("type"));
Log.d(TAG, json.getString("data"));
playerNum = Integer.parseInt(json.getString("data"));
Log.d(TAG,"Received... Type : " +json.getString("type")+" Data : "+json.getString("data"));
}
if(json.has("Player1TurnOver"))
{
player1TurnOver = json.getBoolean("Player1TurnOver");
}
if(json.has("Word"))
{
String b = json.getString("Word");
bWord = new char[b.length()];
for(int i = 0; i < b.length(); i++)
{
bWord[i] = b.charAt(i);
}
wordLength = bWord.length;
}
}
catch(JSONException e)
{
}
}
But this is never called from the server even though the client has a listener as such:
mClient = new WebSocketClient(URI.create("ws://some_ip:8080/wstest"), new WebSocketClient.Listener()){
And the listener is initialised within the websocket library class
public interface Listener {
public void onConnect();
public void onMessage(String message);
public void onMessage(byte[] data);
public void onDisconnect(int code, String reason);
public void onError(Exception error);
}
I can't seem to figure out why this isn't working properly. As it has worked before...
Sometimes it is not correctly detected when a device looses internet connection (Java is not that smart in this case ;) )
Apart from this. Could you maybe activate the debug printouts with WebSocketImpl.DEBUG = true;
The lib will automatically send pings to the endpoints at specific interval and if no ping was received it assumes that the endpoint got disconnected!
Good morning, I have the following code:
int numero = 22492;
String PhnNoStr = String.valueOf (numero);
String transaction = WriteText(tipoTransacao);
String SmsStr = "ECART" + "" + transaction + idToken;
System.out.println ("Message:" + smsStr);
MessageConnection msgCon = null;
msgCon = (MessageConnection) Connector.open ("sms :/ /" + + phnNoStr ": 500");
TextMessage TxtMsg = (TextMessage) msgCon.newMessage (MessageConnection.TEXT_MESSAGE);
txtMsg.setPayloadText (smsStr);
msgCon.send (TxtMsg);
so I send that message by default it returns me a message. I can send and receive this message, however I need to intercept when I receive this message, does anyone know how I can do this?
Thank you
You can use PushRegistry to have your midlet launched when a SMS is received and midlet is not running.
PushRegistry.registerConnection("sms://:500", "your_package.Your_MIDlet", "*");
To handle incoming SMS, you need to open connection and listen for incoming message, eg:
class SMSHandler implements MessageListener, Runnable {
public void start() {
...
connection = (MessageConnection) Connector.open("sms://:500", Connector.READ);
connection.setMessageListener(this);
}
public void notifyIncomingMessage(MessageConnection messageConnection) {
(new Thread(this)).start();
}
public void run() {
final Message message = connection.receive();
...
}
(The reason for processing the message in another thread is that blocking I/O should not be done in system callback - at least WTK emulator will print warning, and on some phones midlet will just freeze).