Pebble JS app_message_outbox_send() in a for loop - pebble-watch

I am using sdk2 for pebble, with the js appmessage features:
I am trying to send consecutive messages to pebble js on the phone, for each one of my menu items. A variable movie_count = 5 exists, and I use this for looping, It gets logged out as 5 as the code shows below, so it should be getting to all 5 , logging errors at least, but it just doesn't log anything after the first time:
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
int i;
APP_LOG(APP_LOG_LEVEL_DEBUG, "movie_count int %u", movie_count);
for(i = 0;i<movie_count;i++){
Tuplet build_menu_tuple = TupletInteger(BUILD_MENU_KEY, 1); // just a flag for the appmessage js code
Tuplet menu_id_tuple = TupletInteger(MENU_ID_KEY, i);
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
if (iter == NULL) {
return;
}
dict_write_tuplet(iter, &build_menu_tuple);
dict_write_tuplet(iter, &menu_id_tuple);
dict_write_end(iter);
app_message_outbox_send();
}
}
in JS appmessage
this code in the js is executed, although only once, I have logged the output in my in_receiver() callback in my watchapp, and my first item gets logged, but the logger just quits after that... Is this because the watchapp cannnot send blutooth messages in a loop like this? Is there a way to make sure the message is sent, or pause the execution so it sends at a slower pace? (the movies_json exists above the code below, i left it out for brevity, but it is there, a json object with an inner array of movies)
if(e.payload.build_menu){
var menu_id = e.payload.menu_id;
console.log("menu_id" + menu_id);
Pebble.sendAppMessage({"title":movies_json.movies[menu_id].title,
"stars":movies_json.movies[menu_id].stars,
"menu_id":menu_id
});
console.log("movie title:" + movies_json.movies[i].title);
}
in_recived_handler callback code to handle messages from the js
this code is in the callback that takes in messsages from the phones js... it only gets to the first item, logs just the first item's menu_id and title, and then logging just stops.
if(menu_id_tuple){
int menu_id;
menu_id = menu_id_tuple->value->int32;
char movie_title[30];
strncpy(movie_title, movie_title_tuple->value->cstring, 30);
APP_LOG(APP_LOG_LEVEL_DEBUG, "In received handler movie_title: %s" , movie_title);
APP_LOG(APP_LOG_LEVEL_DEBUG, "In received handler menu_id: %u" , menu_id);
}

You need to wait until the first message is sent to send the next one.
The proper way to do this is to register a callback for the outbox_sent event and to queue the next message in this event.
Explanation
There is only one bluetooth buffer on pebble and it can only hold one message at a time. If you send messages in a for loop, this buffer gets filled with the first message and all the other messages are rejected.
You would see the error messages if you checked the return value of app_message_outbox_send(). You should also implement a AppMessageOutboxFailed handler.

Related

Is There way to find the queue is empty using rabbit-template

I have subscriber which collects the messages until reaches the specified limit and then pass collected messages to the processor to perform some operations. Code works fine, problem is subscriber waits Until it collects specified number messages. If we have lesser message program control will not pass to processor.
For example Lets say my chunk size is 100 and if I have 100 or multiple of 100 messages then program works fine But if I have messages < 100 or 150 some of messages are read by subscriber but they were never passed to processor. Is there way I can figure-out is that Queue is empty using rabbit template so that I can check that condition and break the loop
#RabbitListener(id="messageListener",queues = "#{rabbitMqConfig.getSubscriberQueueName()}",containerFactory="queueListenerContainer")
public void receiveMessage(Message message, Channel channel, #Header("id") String messageId,
#Header("amqp_deliveryTag") Long deliveryTag) {
LOGGER.info(" Message:"+ message.toString());
if(messageList.size() < appConfig.getSubscriberChunkSize() ) {
messageList.add(message);
deliveryTagList.add(deliveryTag);
if(messageList.size() == appConfig.getSubscriberChunkSize()) {
LOGGER.info("------------- Calling Message processor --------------");
Message [] messageArry = new Message[messageList.size()];
messageArry = messageList.toArray(messageArry);
LOGGER.info("message Array Length: "+messageArry.length);
messageProcessor.process(messageArry);
messageList = new ArrayList<Message>(Arrays.asList(messageArry));
LOGGER.info("message Array to List conversion Size: "+messageList.size());
LOGGER.info("-------------- Completed Message processor -----------");
eppQ2Publisher.sendMessages(messageList, channel, deliveryTagList);
messageList.clear();
deliveryTagList.clear();
}
} else {
// do nothing..
}
There are two ways to achieve this.
Add an #EventListener to listen for ListenerContainerIdleEvents which are published when no messages have been received for some time; set the container's idleEventInterval property. The source of the event is the listener container; it contains the #RabbitListener's id. See Detecting Idle Consumers.
Use RabbitAdmin.getQueueProperties().
You can use RabbitAdmin.getQueueInfo("queue name").getMessageCount() that will be 0 for empty queue.

CLI Dart: onPause, onResume, onDone not firing up as expected

I am experimenting Dart, and I can't explain two observations.
I wonder why the "onDone" handler assigned to a stream subscription does not fire up.
I wonder why the "onPause" and "onResume" handlers fire up only once.
The code:
import 'dart:async';
import 'dart:io';
/// This class encapsulates all the necessary data used by the "onValue" event
/// handler (the construct avoids using global variables).
class OnValueHandlerContainer {
static StreamSubscription<int> _streamSubscriber;
static setStreamSubscriber(StreamSubscription<int> stream) {
_streamSubscriber = stream;
}
// This static method is the handler executed when a event is received through
// the stream.
//
// WARNING: you have absolutely no idea when this handler will be executed.
// Do not assume that it will be executed right after the execution of the code
// that emits an event. It may be executed several lines (of codes) below the
// line that emits the event. It may well be executed after the end of the
// script.
static void onValue(int value) {
// At this point: the state of the subscription is (inevitably) "active".
print("onValue: An event has been raised. The associated value is ${value}!");
print(" Pause the subscription. Wait for 1 second. Resume the subscription");
// Note 1: once a Dart function starts executing, it continues executing until
// it exits. When managing interrupts in C, it is necessary to protect
// interrupt handlers from being interrupted. This is not the case in
// Dart : a function (and, thus, an event handler) cannot be interrupted
// by the occurrence of another event.
// => The code below has no sense, other than experimentation.
// Note 2: while paused, the subscription will not fire any events. If it receives
// events from its source, they will be buffered until the subscription
// is resumed.
_streamSubscriber.pause();
sleep(Duration(seconds: 1));
_streamSubscriber.resume();
// At this point: the state of the subscription is "active".
}
}
main() async {
// Create a controller.
// A StreamController gives you a new stream and a way to add events to the stream
// at any point, and from anywhere. The stream has all the logic necessary to handle
// listeners and pausing. You return the stream and keep the controller to yourself.
StreamController<int> sc = StreamController<int>(
onListen: () => print("Controller: the stream has been assigned a listener!"),
onCancel: () => print("Controller: the stream has been canceled!"),
// As you may notice, the event handlers are not executed every time the
// subscription gets paused or resumed.
//
// This behaviour comes from these facts:
// - Dart is single-threaded.
// - An event handler cannot be interrupted: once a Dart function starts
// executing, it continues executing until it exits. In other words, Dart
// functions can’t be interrupted by other Dart code.
// See https://webdev.dartlang.org/articles/performance/event-loop
// - A stream is a FIFO.
onPause: () => print("Controller: the stream has been paused!"),
onResume: () => print("Controller: the stream has been resumed!")
);
// Get the stream created by the stream controller.
// Right now, this stream has no assigned listener.
Stream<int> stream = sc.stream;
print("Does the stream provided by the controller have a listener ? ${sc.hasListener ? 'yes' : 'no'} - the answer should be no.");
// Push values into the stream controlled by the stream controller.
// Because no listener subscribed to the stream, these values are just stored
// into the stream.
for(int i=0; i<3; i++) {
print("Send the value ${i} into the stream.");
sc.add(i);
}
// Add a listener to the stream.
// Now the stream has an assigned listener.
StreamSubscription<int> subscriber = stream.listen(OnValueHandlerContainer.onValue);
OnValueHandlerContainer.setStreamSubscriber(subscriber);
subscriber.onDone(() => print("The subscription is done!"));
print("Does the stream provided by the controller have a listener ? ${sc.hasListener ? 'yes' : 'no'} - the answer should be yes.");
// Wait for 10 seconds.
print("Start waiting for 10 seconds");
Future.delayed(Duration(seconds: 10)).then((var v) => print("10 seconds ellapsed!"));
print("End of script");
}
The result:
Does the stream provided by the controller have a listener ? no - the answer should be no.
Send the value 0 into the stream.
Send the value 1 into the stream.
Send the value 2 into the stream.
Controller: the stream has been assigned a listener!
Does the stream provided by the controller have a listener ? yes - the answer should be yes.
Start waiting for 10 seconds
End of script
onValue: An event has been raised. The associated value is 0!
Pause the subscription. Wait for 1 second. Resume the subscription
Controller: the stream has been paused!
onValue: An event has been raised. The associated value is 1!
Pause the subscription. Wait for 1 second. Resume the subscription
onValue: An event has been raised. The associated value is 2!
Pause the subscription. Wait for 1 second. Resume the subscription
Controller: the stream has been resumed!
10 seconds ellapsed!
Basically, the code provided performs the following actions :
A stream controller is created.
3 events are injected into the stream provided by the controller.
A listener subscribes to the stream provided by the controller.
We assign an "onDone" handler to the listener subscription.
Within the stream listener (OnValueHandlerContainer::onValue) we pause and resume the subscription.
The stream listener fires up 3 times, as expected.
However:
the "onDone" handler is never executed. I expect it to be executed at the end of the script execution, while the controller is being destroyed (and, thus, the subscription gets closed).
the "onPause" and "onResume" handlers fire up only once. I expect them to be executed 3 times.
Any idea ?
The reason you don't get a "done" event is that you never close the stream subscription.
The reason you don't get more "pause" events is that the stream subscription is clever.
The first thing you do is to add a lot of events, before anyone even listens to the stream. You should never do that in real code, instead only start adding events when the onListen is called, and stop again when onPause is called, until the subscription is resumed.
Here, the stream subscription gets stuffed up with a number of events, then it delivers one event, and then the subscription is paused.
The subscription dutifully reports that back to the controller.
Then the subscription gets a resume. This is where it gets clever. Since it already has events to deliver, it does not report the resume back to the controller. It doesn't actually want more events right now, there are plenty to deliver. And so it delivers the buffered events, one at a time, until the buffer is empty. At that point, it reports the resume back to the controller.
The controller reports that work has been resumed, but since nobody adds any more events, and nobody calls close, nothing further will happen.

Can't pass OVERLAPPED object to WSAGetOverlappedResult

I'm trying to develop req/res server by using overlapped io according to this example.
The problem is that in the same time there could be multiple sends to the same socket and I can't pass overlapped structure to the WSAGetOverlappedResult to manage send event properly. The main loop looks like:
while (TRUE) {
index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, TRUE);
if (index == WSA_WAIT_FAILED) {
printf("Wait failed w/err %d\n", WSAGetLastError());
continue;
}
index -= WSA_WAIT_EVENT_0;
if (!WSAEnumNetworkEvents(SocketArray[index]->Socket, EventArray[index], &NetworkEvents)) { // Multiple events max exist
if (NetworkEvents.lNetworkEvents & FD_ACCEPT)
ManageAccept(index, NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_READ)
ManageRead(index, NetworkEvents);
if (NetworkEvents.lNetworkEvents & FD_WRITE)
ManageWrite(index, NetworkEvents);
}
}
Then I send messages from method ManageRead to the client socket with
WSASend(SocketArray[index]->Socket, &(over->wsabuf), 1, &SendBytes, 0, over, NULL)
And when overlapped send completed I can't really realize in the method ManageSend which of the overlapped structures was actually sent with the call WSAGetOverlappedResult:
WSAGetOverlappedResult(SocketArray[index]->Socket, over, &SendBytes, FALSE, &flags)
I have to use WorkerRoutine temporary to gain control over sending but perhaps somebody knows how to address the issue. Or may there is some different method which returns the overlapped structure which was completed?

Send message only once instead of periodically

I have developed a scenario where at first the vehicles send a self messsage and upon reception of the self message vehicles send a message to RSU.
The self message code is written in the initialize() method. But during simulation the vehicles send the message to RSU every second.
I want the message to be sent only once. What should I do?
I have attached the handleSelfmessage method of my TraCIDemo11p.cc class.
if(msg->isSelfMessage()==true)
{
cModule *tmpMobility = getParentModule()->getSubmodule("veinsmobility");
mobility = dynamic_cast<Veins::TraCIMobility*>(tmpMobility);
ASSERT(mobility);
t_channel channel = dataOnSch ? type_SCH : type_CCH;
WaveShortMessage* wsm = prepareWSM("data", dataLengthBits, channel, dataPriority, -1,2);
wsm->setSenderAddress(myAddress);
wsm->setRecipientAddress(1001);
sendMessage(wsm->getWsmData());
}
Your approach seems right, but obviously you have some problem in your implementation.
Alternatively you can create a new message and send it to yourself
myOneTimeMsg = new cMessage("OneTimeMsg");
scheduleAt(simTime()+1.0, myOneTimeMsg); // this will send the message at t=currentTime+1.0 seconds
Then you can handle that message as follows:
if(msg->isSelfMessage()==true){
if (msg == myOneTimeMsg) {
// do what you need next...
Amending the answer of #user4786271:
The handleSelfMsg method of TraCIDemo11p.cc obviously is executed for every self-message which this module receives - possibly also non WSMs. So if you just added the given code there, it will send a WSM for every of those self-messages. Thus, only checking for self-message type is not enough. You need to create a new message type and check for that type as shown by #user4786271.

NetMQ PUSH socket blocks indefinitely when it reaches HWM

I'm using NetMQ (Nuget 3.3.2.2) on .NET 4.5 and I have a single fast generator process with a PUSH socket, and a single slow consumer process using a PULL socket. If I send enough messages to hit the sending HWM, the sending process blocks the thread indefinitely.
Some contrived (generator) code which illustrates the problem:
using (var ctx = NetMQContext.Create())
using (var pushSocket = ctx.CreatePushSocket())
{
pushSocket.Connect("tcp://127.0.0.1:42404");
var template = GenerateMessageBody(i);
for (int i = 1; i <= 100000; i++)
{
pushSocket.SendMoreFrame("SampleMessage").SendFrame(Messages.SerializeToByteArray(template));
if (i % 1000 == 0)
Console.WriteLine("Sent " + i + " messages");
}
Console.WriteLine("All finished");
Console.ReadKey();
}
On my configuration, this will usually report it has sent about 5000 or 6000 messages, and will then simply block. If I set the send HWM set to a large value (or 0), then it sends all of the messages as expected.
It looks like it's waiting to receive another command before it tries again, here: (SocketBase.TrySend)
// Oops, we couldn't send the message. Wait for the next
// command, process it and try to send the message again.
// If timeout is reached in the meantime, return EAGAIN.
while (true)
{
ProcessCommands(timeoutMillis, false);
From what I've read in the 0MQ guide, blocking on a full PUSH sockeet is the correct behaviour (and is what I want it to do), however I would expect it to recover once the consumer has cleared its queue.
Short of using some sort of TrySend pattern and dealing with the block myself, is there some option I can set or some other facility I can use to have the PUSH socket attempt to resend blocked messages periodically?

Resources