I am trying to get a message from the MQTT Broker using the Android service, but it does not work.
The library used is the Paho MQTT library, and the source code is as follows.
final MqttConnectOptions hIoTConnectionOptions = new MqttConnectOptions();
hIoTConnectionOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1);
hIoTConnectionOptions.setAutomaticReconnect(true);
hIoTConnectionOptions.setCleanSession(false);`
try {
hIoTAndroid = new MqttClient(ip_addr, clientID, new MemoryPersistence());
IMqttToken conToken = hIoTAndroid.connectWithResult(hIoTConnectionOptions);
hIoTAndroid.setCallback(MqttMessagingService.this);
conToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.d(TAG, "onSuccess");
hIoTAndroid.setCallback(MqttMessagingService.this);
try {
IMqttToken subToken = hIoTAndroid.subscribeWithResponse(subtopic, 1);
subToken.setActionCallback(new IMqttActionListener() {
#Override
public void onSuccess(IMqttToken asyncActionToken) {
Log.i(TAG, "Successfully subscribe to: " + subtopic);
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d(TAG, "Couldn't subscribe to: " + subtopic);
}
});
} catch (MqttException | NullPointerException ex) {
ex.printStackTrace();
}
}
#Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
Log.d(TAG, "Failed Connection");
}
});
} catch (MqttException ex) {
Log.d(getClass().getCanonicalName(), "Connection attempt failed with reason code = " + ex.getReasonCode() + ":" + ex.getCause());
}
#Override
public void connectComplete(boolean reconnect, String serverURI) {
Log.d(TAG, "Connection is established....");
}
#Override
public void connectionLost(Throwable cause) {
Log.d(TAG, "The Connection was lost,,");
}
#Override
public void messageArrived(String topic, MqttMessage message) throws Exception {
Log.i(TAG, new String(message.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken token) {
Log.d(TAG, "Sent Message !");
}
The publish and deliveryComplete functions work fine, but the subscribe function and messagArrived do not work. Why?
Related
I would like to add a Filter in Spring Cloud Data Flow (SCDF) to debug and see how it works when receiving some requests.
I have tried to implements javax.servlet.Filter and override doFilter method but It's seem not work because there are some default Filter of SCDF had been started before my Filter class.
Are there any way do write a filter for SCDF? Is it possible if I apply this link for this purpose?
This is my Filter class:
#Component
public class CustomFilter implements Filter {
#Override
public void destroy() {
System.out.println("init fillter ");
}
#Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
try {
HttpServletRequest req = (HttpServletRequest) arg0;
ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(
(HttpServletResponse) arg1);
ResettableStreamHttpServletRequest wrappedRequest = new ResettableStreamHttpServletRequest(
(HttpServletRequest) req);
logger.info(">>>>>link: " + req.getServletPath() + "?");
for (Entry<String, String[]> entry : req.getParameterMap().entrySet()) {
logger.info(">>>>>param: " + entry.getKey() + ":" + entry.getValue()[0]);
}
String bodyRequest = IOUtils.toString(wrappedRequest.getReader());
logger.info(">>>>>link: " + req.getServletPath() + "?");
for (Entry<String, String[]> entry : req.getParameterMap().entrySet()) {
logger.info(">>>>>param: " + entry.getKey() + ":" + entry.getValue()[0]);
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
transformerFactory.setAttribute("indent-number", 2);
javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
try {
logger.info("Request: " + bodyRequest);
} catch (Exception e) {
logger.info("Request: " + bodyRequest);
}
wrappedRequest.resetInputStream();
arg2.doFilter(wrappedRequest, responseWrapper);
logger.info("Response: " + IOUtils.toString(responseWrapper.getContentInputStream()));
responseWrapper.copyBodyToResponse();
} catch (Exception ex) {
logger.info("doFilter: " + ex);
}
}
#Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("init fillter " + arg0);
}
private static class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper {
private byte[] rawData;
private HttpServletRequest request;
private ResettableServletInputStream servletStream;
public ResettableStreamHttpServletRequest(HttpServletRequest request) {
super(request);
this.request = request;
this.servletStream = new ResettableServletInputStream();
}
public void resetInputStream() {
servletStream.stream = new ByteArrayInputStream(rawData);
}
#Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}
#Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return new BufferedReader(new InputStreamReader(servletStream));
}
private class ResettableServletInputStream extends ServletInputStream {
private InputStream stream;
#Override
public int read() throws IOException {
return stream.read();
}
#Override
public boolean isFinished() {
return false;
}
#Override
public boolean isReady() {
return false;
}
#Override
public void setReadListener(ReadListener arg0) {
}
}
}
}
Spring Cloud Data Flow server is inherently a Spring Boot application and hence it allows you to inject specific configuration beans into Data Flow configuration to extend/customize.
In your case, you can create a bean that extends javax.servlet.http.HttpFilter or implements javax.servlet.Filter and have that bean injected into SCDF configuration.
This mqtt subscriber code works fine. I can easily subscribe to messages which are published at broker.hivemq.com with respective topic.
public class AccelerometerSubscriber implements MqttCallback,
IMqttActionListener {
public static void main(String[] args) throws MqttException {
int QUALITY_OF_SERVICE = 2;
MqttClient client=new MqttClient("tcp://broker.hivemq.com:1883",
MqttClient.generateClientId());
client.setCallback( new SimpleMqttCallBack() );
client.connect();
System.out.println("Subscribing ....");
client.subscribe("MQTT Examples"); }
System.out.println("some action"); //------------right here--------------
public void connectionLost(Throwable throwable) {
System.out.println("Connection to MQTT broker lost!"); }
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
System.out.println("Message received:\n\t"+ new String(mqttMessage.getPayload()) );
}
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
// not used in this example
}}
Now I want to perform action only when a message is received. I'm unable to do that.
You have a class (AccelerometerSubscriber) that implements the interface MqttCallback, use an instance of it instead of doing client.setCallback( new SimpleMqttCallBack() );
public class AccelerometerSubscriber implements MqttCallback, IMqttActionListener {
public static void main(String[] args) throws MqttException {
AccelerometerSubscriber as = new AccelerometerSubscriber();
int QUALITY_OF_SERVICE = 2;
MqttClient client = new MqttClient("tcp://broker.hivemq.com:1883", MqttClient.generateClientId());
client.setCallback(as);
client.connect();
System.out.println("Subscribing ....");
client.subscribe("MQTT Examples");
}
#Override
public void connectionLost(Throwable throwable) {
System.out.println("Connection to MQTT broker lost!");
}
#Override
public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
//message is received is here!!!
System.out.println("Message received:\n\t" + new String(mqttMessage.getPayload()));
}
#Override
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
System.out.println("deliveryComplete");
}
#Override
public void onFailure(IMqttToken arg0, Throwable arg1) {
System.out.println("onFailure");
}
#Override
public void onSuccess(IMqttToken arg0) {
System.out.println("onSuccess");
}
}
My query is I have a printer connected to the Wifi and I am able to connect to that printer using the IP address of the printer but I am not able to print from that printer.
MY code:-
class MakeConnection extends AsyncTask<String, Void, String>{
String check = "NO";
#Override
protected String doInBackground(String... params) {
Socket sock = null;
PrintWriter oStream = null;
try
{
sock = new Socket(ipAddress, 9100);
oStream = new PrintWriter(sock.getOutputStream());
oStream.write("HI,test from Android Device");
check = "yes";
oStream.flush();
}
catch (IOException e)
{
e.printStackTrace();
Logger.LogError(TAG, e.toString());
AppToast.showShortToast(mContext, e.toString());
}
finally {
oStream.close();
try {
sock.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
#Override
protected void onPostExecute(String s) {
Logger.LogError(TAG, check);
super.onPostExecute(s);
}
}
where I am wrong?
I want to create a group to make the current device tablet as the access point, however in the callback method onGroupInfoAvailable() I got a null pointer of group. Why?
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
manager.createGroup(channel, new ActionListener() {
#Override
public void onSuccess() {
manager.requestGroupInfo(channel, new GroupInfoListener() {
public void onGroupInfoAvailable(WifiP2pGroup group) {
if(group != null)
Toast.makeText(SasetBladderPadActivity.this, "Group Passphrase: "
+ group.getPassphrase(), Toast.LENGTH_LONG).show();
else
Toast.makeText(SasetBladderPadActivity.this, "Group is null ",
Toast.LENGTH_LONG).show();
}
});
}
#Override
public void onFailure(int arg0) {
// TODO Auto-generated method stub
Toast.makeText(SasetBladderPadActivity.this, "Create group failed: " + arg0, \
Toast.LENGTH_LONG).show();
}
});
I think you need to implement the grouplistener and then #override the ongroupinfoavailable method. On success is just the asyn call. Actual callback needs to be modified.
Yes, the group is created but not shown. I will suggest to do it with the trick of implementing countdowntimer(or you may use any other timer) to start the requestGroupInfo() after a second. The modified code will be:
manager = (WifiP2pManager) getSystemService(Context.WIFI_P2P_SERVICE);
channel = manager.initialize(this, getMainLooper(), null);
manager.createGroup(channel, new ActionListener() {
#Override
public void onSuccess() {
new CountDownTimer(1000, 1000) {
public void onTick(long millisUntilFinished) {}
public void onFinish() {
manager.requestGroupInfo(channel, new GroupInfoListener() {
public void onGroupInfoAvailable(WifiP2pGroup group) {
if(group != null)
Toast.makeText(SasetBladderPadActivity.this, "Group Passphrase: "
+ group.getPassphrase(), Toast.LENGTH_LONG).show();
else
Toast.makeText(SasetBladderPadActivity.this, "Group is null ",
Toast.LENGTH_LONG).show();
}
});
}
}.start();
}
#Override
public void onFailure(int arg0) {
...
I am getting RunTime Exception when I am Running this code..Please Go Through it and Help me if you have any idea. Thanks..
private void sendSMS(String phone, String message) throws IOException
{
// TODO Auto-generated method stub
Dialog.alert("Hello..In Send SMS Function");
System.out.println("in send sms function");
MessageConnection conn =
(MessageConnection)Connector.open("sms://+919099956325");
TextMessage tmsg = (TextMessage) conn.newMessage(MessageConnection.TEXT_MESSAGE);
tmsg.setAddress("sms://+919429441335");
tmsg.setPayloadText("HIIiii");
System.out.println("Text message is>>"+tmsg);
conn.send(tmsg);
}
instead of
System.out.println("Text message is>>"+tmsg);
use
System.out.println("Text message is>>"+tmsg.getPayloadText());
Also Connector.open is a blocking operation and should not be called from a main event thread.
You have Dialog.alert which will only work on a event thread. Do this
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("Hello..In Send SMS Function");
}
});
Try this code . this starts a new thread and calls sendsms method
new Thread(new Runnable() {
public void run() {
try {
sendSMS("123456789","message");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
private void sendSMS(String phone, String message) throws IOException
{
try {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("Hello..In Send SMS Function");
}
});
System.out.println("in send sms function");
MessageConnection conn =
(MessageConnection)Connector.open("sms://+919099956325");
TextMessage tmsg = (TextMessage) conn.newMessage(MessageConnection.TEXT_MESSAGE);
tmsg.setAddress("sms://+919429441335");
tmsg.setPayloadText("HIIiii");
System.out.println("Text message is>>"+tmsg.getPayloadText());
conn.send(tmsg);
} catch (Exception e) {
System.out.println("Exception is >>"+e.toString());
}
}