I'm currently using Topic based communication using JADE. I'm able to register a JADE agent using jade.core.messaging.TopicManagementFEService thereby connecting to the main-container in the same platform.
The details are below:
Main-Container: a simple LAMP/WAMP Server that hosts the Main-Container.
Client: An Android Emulator(testing purpose) to connect to the main-container.
Currently,
Server starts the main-container
Android emulator connects to the Main-container successfully (Agent created along with Topic Mgmt Service enabled)
Server is sending messages based on a specific topic.
But my Android Client is not able to receive this message although the topic registered is the same on both ends!
You can see the code below:
Server Side:
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
final AID sensorTopic = topicHelper.createTopic("JADE");
topicHelper.register(sensorTopic);
addBehaviour(new TickerBehaviour(this, TIMER_VALUE_IN_MILLISECONDS) {
private static final long serialVersionUID = -2567778187494378326L;
public void onTick() {
ACLMessage msg = new ACLMessage(ACLMessage.INFORM);
msg.addReceiver(eventTopic);
msg.setContent(eventValue);
myAgent.send(msg);
}
});
Android Side:
// Registering on Android Side as well
TopicManagementHelper topicHelper = (TopicManagementHelper) getHelper(TopicManagementHelper.SERVICE_NAME);
topic = topicHelper.createTopic("JADE"); // See, same topic!
topicHelper.register(topic);
behaviour = new myBehaviour(this, TIMER_VALUE_IN_MILLISECONDS, topic);
addBehaviour(behaviour);
private class myBehaviour extends TickerBehaviour {
private static final long serialVersionUID = 4782913834042415090L;
AID topic;
Agent agent;
MessageTemplate tpl;
public myBehaviour(Agent a, long period, AID topic) {
super(a, period);
this.agent = a;
this.topic = topic;
}
public void onTick() {
tpl = MessageTemplate.MatchTopic(topic);
ACLMessage msg = receive(tpl);
if (msg != null) {
logger.log(Level.INFO, "Agent "+ agent.getLocalName() +
": Message about topic "+ topic.getLocalName() +" received. \n" +
"Content is " + msg.getContent());
data = msg.getContent();
} else {
logger.log(Level.INFO, "In here..."); // Always executes only this code!
block();
}
}
}
Where am I going wrong here? It always executes the else part in the Android side which is obvious to say that message received is NULL!
Never mind. The logic was wrong. The Android-Agent was not identifying itself to the Central-Agent.
I set the Ontology so that the Central Agent is able to identify such message and sends the message accordingly. Now, it is receiving messages!
Self-help works sometimes! ;-)
Receiving topic messages doesn't work correctly with Android up to version 4.3.0 in JADE. Android can send out topic messages but can't receive them. I found this out through my own issues. I've posted more info about it in my own question on stack overflow.
Take a look. JADE Leap Android App unable to receive topic messages
Related
I am developing an app that communicates using the MAVLINK protocol. I am using dronefleet for this purpose. My app has a service which runs a ReadThread that checks the incoming MAVLINK messages for their type. ReadThread then sends messages to the UI for updating some TextViews with the drone's information like battery status, etc. Here is my code.
ReadThread in DService.java
import io.dronefleet.mavlink.MavlinkMessage;
import io.dronefleet.mavlink.common.Attitude;
import io.dronefleet.mavlink.common.SysStatus;
public static final int ATTITUDE = 1;
public static final int SYS_STATUS = 2;
private class ReadThread extends Thread {
private AtomicBoolean keep = new AtomicBoolean(true);
#Override
public void run() {
while(keep.get()){
if(inputStream == null)
return;
MavlinkMessage message;
try {
---------------------get MAVLINK message from stream here---------------
message = mavlinkConnection.next();
-------------------check MAVLINK message type and then send message to UI for updating related fields--------------------
if(message.getPayload() instanceof Attitude) {
MavlinkMessage<Attitude> attitudeMessage = (MavlinkMessage<Attitude>)message;
myHandler.obtainMessage(ATTITUDE, attitudeMessage).sendToTarget();
}
----------------removing comments causes app to crash---------------------
/*if(message.getPayload() instanceof SysStatus) {
MavlinkMessage<SysStatus> sysStatusMessage = (MavlinkMessage<SysStatus>)message;
int battery = sysStatusMessage.getPayload().batteryRemaining();
myHandler.obtainMessage(SYS_STATUS, Integer.toString(battery)).sendToTarget();*/
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setKeep(boolean keep) {
this.keep.set(keep);
}
}
handleMessage() in MainActivity.java
switch (msg.what) {
case DService.SYS_STATUS:
String battery = (String) msg.obj + "%";
myActivity.get().batteryView.setText(battery);
case DService.ATTITUDE:
MavlinkMessage<Attitude> message = (MavlinkMessage<Attitude>) msg.obj;
String pitch = Float.toString(message.getPayload().pitch());
String roll = Float.toString(message.getPayload().roll());
String yaw = Float.toString(message.getPayload().yaw());
myActivity.get().pitchView.setText(pitch);
myActivity.get().rollView.setText(roll);
myActivity.get().yawView.setText(yaw);
break;
}
}
My problem is my app is crashing if I am checking for more than one type of MAVLINK message in my ReadThread. If I check for (say) either SYS_STATUS or ATTITUDE, then the corresponding TextViewss in the UI are getting updated seamlessly every second (which is the rate of messages sent by MAVLINK). But not for 2 message classes. If I remove comments from one if block, my app crashes.
Whats could be the reason? Is my handleMessage() wrong? Do I need to use MessageQueue or some other android mechanism? Should I run separate threads like ReadThread for each MAVLINK message type?
I am developing on Ubuntu 18, and using Android Studio.
Does logcat have any exceptions being thrown by your program before it crashes?
I would not use multiple threads for each MAVLink message type's handlemessage because I'm guessing the dronefleet parser for the MAVLink connection is stateful (MAVLink uses a magic prefix and payload length to delimit packets) and it would probably either break or be nearly synchronous if called from multiple threads.
If you're worried that you might be sending updates too frequently you could have the read thread store the values from the different MAVLink messages and a separate thread send updates at a fixed interval based on either the latest value for each message or on the set of messages received since the last update.
I have a spring boot application which will publish message on azure Queue. I have one more azure queueTrigger function written in Java which will listen to the same queue to which spring boot application has published a message. The queueTrigger function not able to detected messages published on queue.
Here is my publisher code
public static void addQueueMessage(String connectStr, String queueName, String message) {
try {
// Instantiate a QueueClient which will be
// used to create and manipulate the queue
QueueClient queueClient = new QueueClientBuilder()
.connectionString(connectStr)
.queueName(queueName)
.buildClient();
System.out.println("Adding message to the queue: " + message);
// Add a message to the queue
queueClient.sendMessage(message);
} catch (QueueStorageException e) {
// Output the exception message and stack trace
System.out.println(e.getMessage());
e.printStackTrace();
}
}
Here is my queueTrigger function app code
#FunctionName("queueprocessor")
public void run(
#QueueTrigger(name = "message",
queueName = "queuetest",
connection = "AzureWebJobsStorage") String message,
final ExecutionContext context
) {
context.getLogger().info(message);
}
I'm passing same connection-String and queueName, still doesn't work. If i run function on my local machine then it gets triggered but with error error image
As the official doc suggests,
Functions expect a base64 encoded string. Any adjustments to the encoding type (in order to prepare data as a base64 encoded string) need to be implemented in the calling service.
Update sender code to send base64 encoded message.
String encodedMsg = Base64.getEncoder().encodeToString(message.getBytes())
queueClient.sendMessage(encodedMsg);
In my app (streaming series, movies) I have a section for users that can set Reminder for the series or movies. And I implement Pusher to receive server message for reminding data.
Is it true that I connect to channel for each item in the reminder list?? or I should connect to the pusher once and in the pusher event get related series/ movies message?(Server-side implemented pusher for each reminder list items, should we change server-side implementation or I can connect to pusher for each items? )
This is my Implementation for pusher:
public Pusher getPusher() throws Exception {
if (pusher == null) {
HttpAuthorizer auth = new HttpAuthorizer(BuildConfig.PUSHER);
HashMap<String, String> authHeader = new HashMap<>();
authHeader.put("Authorization", SharedPref.INSTANCE.read(AUTH_TOKEN, ""));
auth.setHeaders(authHeader);
PusherOptions option = new PusherOptions();
option.setCluster(BuildConfig.PUSHER_CLUSTER);
option.setAuthorizer(auth);
pusher = new Pusher(BuildConfig.PUSHER_KEY, option);
pusher.subscribePrivate("private-app_ch." + serialId, new PrivateChannelEventListener() {
#Override
public void onAuthenticationFailure(String s, Exception e) {
Timber.i("pusher onAuthenticationFailure " + e.getMessage());
}
#Override
public void onSubscriptionSucceeded(String s) {
Timber.i("pusher onSubscriptionSucceeded: " + s);
}
#Override
public void onEvent(String s, String s1, String result) {
Timber.i("pusher onEvent" + s + ":" + s1);
Timber.i("pusher onEvent" + result);
}
}, "App\\Events\\AppBroadcastEvent");
}
return pusher;
}
The best practice for this would be to maintain one connection to Channels but make a subscription for each item in the reminder list.
So you would call pusher.subscribePrivate for each item in the reminder list and then on the server side publish to each individual Channel when a reminder needs to be sent.
For example if a user wanted to be reminded about 'Stranger Things' and 'Orange is the new black' you would subscribe to both:
pusher.subscribePrivate("private-app_ch.strangerthings"
and
pusher.subscribePrivate("private-app_ch.orangeisthenewblack"
Your server would then publish reminders about 'Stranger Things' to the Stranger things channel and OISTNB to the OISTNB channel and so on.
This way only relevant updates are sent to the client (server-side filtering). If you only subscribe to one channel the client will get messages they may not want updates about and you would have to filter these out on the client side.
This is also explained here: https://support.pusher.com/hc/en-us/articles/360025398514-Should-i-subscribe-to-lots-of-Channels-
One additional point that is worth considering is that Channels will only maintain an active connection when the app is open. The connection will be closed when the app is backgrounded/closed. This means for reminders to be sent the user would always have to be in your app. You may want to consider also sending push notifications when the app is closed so the user does not miss reminders.
I am trying to connect to a bitcoin node using the ZMQ library for Java. the problem is that when I try to receive a response the code remains frozen. Returns nothing.
This is my code:
public class CBETest {
private static final String TEST_URL = "obelisk.airbitz.co";
public static void main(String[] args) {
System.out.println("\t--- ZMQ ---");
Ctx c = zmq.ZMQ.createContext();
SocketBase s = c.createSocket(zmq.ZMQ.ZMQ_DEALER);
zmq.ZMQ.connect(s, "tcp://"+TEST_URL+":9091");
System.out.println("Connected!");
int sent = zmq.ZMQ.send(s, "blockchain.fetch_last_height", 0);
System.out.println("Sent: " + sent);
Msg msg = zmq.ZMQ.recv(s, 0);
System.out.println("Response " + Arrays.toString(msg.data()));
}
}
The code freezes in the line Msg msg = zmq.ZMQ.recv(s, 0);. I am using the calls described here for the full node implemetation. Thanks in advance!
The code is not freezing, it is blocking while waiting to receive a message.
I would suggest you put your above code in a thread/runnable class and use localhost as the TEST_URL and start the server.
Then create another Runnable class with a client that tries to connect to that port and send back a message and start that thread and see if the message gets through.
There is an example here:
http://zguide.zeromq.org/java:rtdealer
I have a project where we are using ArdanStudios smppclient to connect to an SMPPServer. We can send messages to the SMPP Server and they get delivered to the handset. When the hand set replies or sends to the shortcode we do get a received message event but the message text is blank.
We are using CloudHopper internally to simulate the SMPP Server, I want to confirm that there isn't a problem on our end when receiving messages but I can not figure out a way to simulate an MO (mobile originated) message sent from Cloudhopper server to our connected ArdanClient. Any ideas ?
You have two questions in one Pal. I suggest you break it up. For the first one basically you have to override the firePduRequestReceived methos of class DefaultSmppSessionHandler:
#Override
public PduResponse firePduRequestReceived(PduRequest pduRequest) {
PduResponse response = pduRequest.createResponse();
if (pduRequest.getCommandId() == SmppConstants.CMD_ID_DELIVER_SM) {
processMO(pduRequest);
}
return response;
}
private void processsMO(PduRequest request){
DeliverSm mo = (DeliverSm) request;
int length = mo.getShortMessageLength();
Address sourceAddr = mo.getSourceAddress();
Address destAddr = mo.getDestAddress();
byte[] shortMessage = mo.getShortMessage();
String sms= new String(shortMessage);
//Do Something....
}