Check the condition when a timer is running in CAPL (CANoe) - while-loop

I am running a script in CAPL where I am supposed to notice a change in the value of a signal (for example: signal B) coming from the ECU. At the start of the timer, I change the value of another signal (for example: signal A) and sent it to ECU over CAN Bus. While the timer is running, I want to see the changed value of signal B coming from ECU as a response to the changed value of signal A. After the timer has run out, I want to reset the signal A back to its original value.
*Note: I have called the different signals as Signal A and Signal B only for understanding the question more clearly
Signal A changes the value from 2 to 0.
Signal B has original value of 61, and the changed value can be any number between 0-60.
Timer runs for 4 seconds.
I am using while loop and command (isTimerActive(timer)==1), to check for the change in the value of signal B when the timer is running.
Below is the attached Code ->
variables
{
msTimer Execute;
}
on key 'c'
{
setTimer(Execute,4000);
Write("Test starts");
SetSignal(Signal A, 2);
while (isTimerActive(Execute)==1)
{
if ($Signal B != 61)
{
Write("Test pass");
}
else
{
Write("Test fail");
}
}
}
on timer Execute
{
write("Test over");
setSignal(Signal A, 0);
}
I am executing this code and the value of signal A changes to 2 but
there's no change in the value of signal B. I am using the
(isTimerActive (timer) ==1) in the while loop, is it the correct command
for my problem?
Also, when I run (isTimerActive (timer) ==1), CANoe becomes inactive and
I have to stop CANoe using Task manager.
Any ideas how can I correct my code and get the desired response?
Thanks and Best

CAPL is event-driven. Your only choice is to react on events by programming event handlers, i.e. the functions starting with on ....
During execution of an event handler, the system basically blocks everything until the event handler has finished.
Literally nothing else happens, no sysvars change, no signals change, no timers expire, no bus messages are handled, and so on.
For test-modules and -units the story is a little bit different. There you have the possibility to wait during execution of your code using the various testWaitFor... methods.
With your current implementation of on key ‘c‘you basically block the system, since you have an while loop there waiting for an Timer to expire.
As stated above, this blocks everything and you have to kill CANoe.
Fortunately changes of signals are also events that can be handled.
Something like this should do:
Remove the while block and instead add another event handler like this:
on signal SignalB
{
if(isTimerActive(Execute))
{
if ($SignalB != 61)
{
Write("Test pass");
}
else
{
Write("Test fail");
}
}
}
The code is called when SignalB changes. It then checks whether the Timer is still running and checks the value of the signal.
Instead of $SignalB inside of the handler you can also write this.
In an event handler this is always the object that has caused the event.

Related

Suspend `withTimeout`

My app starts from executing coroutine:
model.viewModelScope.launch(Dispatchers.IO) {
val timeout = withTimeoutOrNull(TIMEOUT) {
//send some initialization server requests
true //timeout=true
}
if (timeout!=null){
// app started ok
} else {
// app freezed on start
}
}
The problem is one of the initialization step - obtain user consent to share his personal data(GDPR) Consent form is a modal popup that waits for user input.But the timer is ticking all this time. Therefore after gdpr user may see app starts too long error.
Is there way to suspend withTimeoutOrNull timer and resume it after some time?
It is not supported out of the box, but you can write your own version of withTimeoutOrNull that would support a pauseable timer. The key idea is to run your block in a separate coroutineScope { ... } and to launch a secondary helper coroutine that would cancel this scope after timeout. Now if you keep a reference to this helper cancellationJob, then you can cancel it when you need to pause your time and restart it when you need to resume timer.
That would give you essentially the same behavior that basic withTimeout has but with an added pauseability. A bit of extra code is needed to implement a withTimeoutOrNull variant. You'll need to catch your cancellation exception and replace it with null result.
A worked-out implementation can be found in this gist: https://gist.github.com/elizarov/c5b0fde43ca14efbb8bcab13ad43c6ca

How to force a libusb event so that libusb_handle_events() returns

Suppose I have a libusb program that just uses the hotplug API. You register a callback and then apparently have to call libusb_handle_events() in a loop which then calls your hotplug callback.
int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
cout << "Device plugged in or unplugged";
}
void main()
{
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
for (;;)
{
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
return 1;
}
return 0;
}
The question is, without timeout hacks how can I exit this event loop cleanly? I can't find any functions that force libusb_handle_events() (or libusb_handle_events_completed()) to return. In theory they could just never return.
Sorry if this is late.
The question could have been phrased better but I'm assuming (from your comment updates) that your actual program resembles something a little closer to this:
int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data) {
cout << "Device plugged in or unplugged";
}
void SomeClass::someFunction() {
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
this->thread = std::thread([this]() {
while (this->handlingEvents) {
int error = libusb_handle_events_completed(context, nullptr);
}
});
}
Let's say your object is being deallocated and, no matter what is happening on the USB bus, you don't care and you want to clean up your thread.
You negate this->handlingEvents and you call thread.join() and the thread hangs for 60 seconds and then execution resumes.
This is done because the default behavior of libusb_handle_events_completed calls libusb_handle_events_timeout_completed and passes in a 60 second timeout interval with plans to make it infinite.
The way you force libusb_handle_events_completed to return is you call libusb_hotplug_deregister_callback which wakes up libusb_handle_events(), causing the function to return.
There is more info about this behavior in the docs.
So your destructor (or wherever you want to stop listening immediately) for the class could look something like this:
SomeClass::~SomeClass() {
this->handlingEvents = false;
libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
if (this->thread.joinable()) this->thread.join();
libusb_exit(this->context);
}
In the function:
int libusb_handle_events_completed(libusb_context* ctx, int* completed)
You can change the value of the completed to "1" so the function will return without blocking
According to their docs:
If the parameter completed is not NULL then after obtaining the event
handling lock this function will return immediately if the integer
pointed to is not 0. This allows for race free waiting for the
completion of a specific transfer.
There is no functions in libusb that force libusb_handle_events() to return.
It's recommended to use libusb_handle_events() in a dedicated thread so your main thread will not be blocked by this call. Even though, if you need to manipulate the call of the event handler you can put the call in a while(condition) and change the condition state in your main thread.
Libusb documentation details this here.

Why is any code executed before this has finished?

Supposing I have a code like this:
[ApiConnection getServerTimeWithBlock:^(BOOL gotTimeResponse){
if(gotTimeResponse)
{
//we're online, got the response from time endpoint
[ApiConnection registerNewCustomerWithBlock:^(NSString* val){
if(val)
{
NSLog(#"val: %#",val);
}
else
{
NSLog(#"no val");
}
}];
}
else
{
//we're offline
}
}];
NSLog(#"TEST");
why is the last NSLog executed before the whole first block has finished execution?
Because the getServerTimeWithBlock: method is asynchronous, so it returns immediately and runs on a background thread. When that thread is complete is calls the completion block.
So, the method runs before your log, but the completion block (usually) doesn't (it might if there was an error or something like that).
Presumably getServerTimeWithBlock: is exectuted asynchronously. When supplying the block, you're telling the APIConnection object what to do when it has finished getting the server time. This will involve network fetches and reading data back, which you don't want to wait for on the main thread as this will cause your UI to freeze. Your program therefore carries on, and the block is executed whenever the fetch is complete.
Note that blocks do not imply that asynchronous or multithreaded code is in use (see NSArray's enumerateWithBlock: method, for example) but it seems very likely to be the case here.

Having a winforms app wait for a few minutes before proceeding

I've seen a few references on Stack Overflow about using the Timer Class to do what I want but I'm not convinced it's the right solution to the problem.
Basically, I have a button (in .NET 4.0) that when clicked will go through a few different subroutines and do certain things:
Restart some services
Launch a command line application that finishes automatically
Launch a second command line application that finishes automatically
Launch a third command line application that finishes automatically
The problem I have right now is that the program just goes through each thing and fires it off as quickly as possible - not a problem except that the third command line application must only fire after the first three are completed.
I had a sleep call in the code, except that this froze the UI and I have a status bar on this application that I wanted to have update to let the user know things are occurring.
I was thinking about a Timer object but I'm not sure that would actually cause there to be a pause before doing the next thing.
I'm using a Process.Start method to fire off the command line applications, so it doesn't actually raise an event. Should I just have my subroutine raise an event and then have the third Process.Start method wait for that event to fire before it goes?
This small snippet might help you. Try to get the idea and implement your own code.
try
{
Process myProcess;
myProcess = Process.Start("Notepad.exe");
while (true)
{
if (!myProcess.HasExited)
{
// Discard cached information about the process.
myProcess.Refresh();
// Print working set to console.
Console.WriteLine("Physical Memory Usage: "
+ myProcess.WorkingSet.ToString());
// Wait 2 seconds.
Thread.Sleep(2000);
}
else {
break;
}
}
// Close process by sending a close message to its main window.
myProcess.CloseMainWindow();
// Free resources associated with process.
myProcess.Close();
}
catch(Exception e)
{
Console.WriteLine("The following exception was raised: ");
Console.WriteLine(e.Message);
}

What are my errors using libevent timout events?

I am trying to learn libevent for use in a future project. I am attempting to create a event that calls it's call back function each time it times out. All the call back function does is print "timeout_cb called" to standard out.
my code for the call back function is:
static void timeout_cb(evutil_socket_t fd, short what, void *arg) {
printf("timeout_cb called");
}
my code for the event is:
struct event *toEvent; // time out event do this every so often
toEvent = event_new(base, -1, EV_TIMEOUT, timeout_cb, NULL); // base is the event base
event_add(toEvent, &five_seconds); //five_seconds is a timeval struct with 5 seconds
The program will compile and run with no errors or warnings but it doesn't print out the phrase in the call back function. I have used similar printf statements in other callback types to verify they were called and that various lines were reached inside the functions, but this does nothing. I waited 30 seconds or so but still nothing printed to the screen. What am I doing wrong the with the pure timeout event.
You'll have to do
event_new(base, -1, 0, timeout_cb, NULL);
Note that there's some convenience macros to add timers, evtimer_new(), evtimer_add(), see the docs