CAPL Programming usage of Timer as a delay - can-bus

I have been writing a CAPL script that would send message on each channel (2 no's) after a certain delay. The following delay i want to generate using SetTimer() and mstimer::isRunning function.
I can use setTimer function but I dont know how to use mstimer::isRunning.
The code is shown below:
Variables{
message * temp = {DLC=8};
mstimer timer1;
}
on timer timer1{
//Do nothing
}
onstart{
for(noofChannel=1;noofChannel<=2;noofChannel++){
settimer(timer1,100);
temp.CAN = noofChannel;
temp.ID = 0xAA;
While (mstimer::isrunning)==0 // I need to write this right.
{ //wait for timer to expire}
Output(temp);
}

Instead of mstimer::isrunning use isTimerActive() method.
isTimerActive() returns 1 if timers is running and 0 if it is expired.
So your code will look like:
on start{
for(noofChannel=1;noofChannel<=2;noofChannel++){
settimer(timer1,100);
temp.CAN = noofChannel;
temp.ID = 0xAA;
While (isTimerActive(timer1) == 1)
{ //wait for timer to expire}
}
Output(temp);
}
}
But I would not recommend doing this. Instead of looping in on start, you can ouput 2nd message through onTimer
on start{
temp.CAN = 1;
temp.ID = 0xAA;
Output(temp);
settimer(timer1,100);
}
on timer timer1{
temp.CAN = 2;
Output(temp);
}
If you want to keep it generic i.e. not restricting to 2 channels, you can take a variable and increment it in timer.

I asked Vector for the same question and they answered it something like this:
“msTimer.isRunning” gives us status of Timer, whether timer running or not
The usability is mentioned below:
on timer myTimer
{
write("Running Status %d",myTimer.isRunning());
}
" timeToElapse() " function can also be used for the following case.
Syntax:
timer t;
setTimer(t,5);
write("Time to elapse: %d",timeToElapse(t)); // Writes 5

/*Solution on how timer works*/
variables
{
mstimer t1,t2;/*millisec timer*/
timer t3;/*sec timer*/
}
on timer t1
{
settimer(t2, 10);/*wait in timer t1 for 10ms and then goes to timer t2*/
}
on timer t2
{
settimer(t3, 10);/*wait in timer t2 for 10ms and then goes to timer t3*/
}
on timer t3
{
settimer(t4, 10);/*wait in timer t3 for 10sec and then goes to timer t4*/
}
on timer t4
{
settimer(t1, 10);/*wait in timer t4 for 10sec and then goes to timer t1*/
}
on start()
{
settimer(t1,10);/*waits here for 10ms and then goes to timer t1*/
}

Related

How to handle "onCancel" of Timer.periodic or Stream.periodic

Whenever a user wants to play some audio, first I want to wait 5 seconds and every second perform an action. Whenever the user pushes play button, I call onPlay() method. My first attempt of it was this:
Timer? _timer; // I might need to cancel timer also when the user pauses playback by pause button or something
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) _timer?.cancel();
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
This attempt was not working correctly as audio.play() run immediately after Timer was initialized, not finished. I found How to make Timer.periodic cancel itself when a condition is reached? and used one of the answers to improve my code like this:
StreamSubscription? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.forEach((_) {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
});
audio.play(_curSong);
}
This worked better, but if the user switches to a different song or pauses playback during the intial phase, _timer?.cancel() will only cancel the stream, so everything after it (audio.play(_curSong)) is still being run. But I would like to cancel not only the stream, but also skip the audio.play() function. So I would like to run audio.play() only after the Timer/Stream finishes properly without cancellation.
Is there any option to handle Stream.periodic or Timer.periodic cancel action ("onCancel")? Or is there a better way to handle this specific task?
Almost there. Your await on .forEach actually returns null. So there is no StreamSubscription as far as I can see.
The callback that might be the simple solution for your problem is the optional onDone in the listen method. This won't be called when Stream is cancelled.
import 'dart:async';
void main() async {
onPlay();
await Future.delayed(Duration(seconds: 2));
// Uncomment me to test it
// _timer?.cancel();
}
StreamSubscription? _timer;
void onPlay() {
int _secondsLeft = 5;
_timer = Stream.periodic(const Duration(seconds: 1))
.takeWhile((_) => _secondsLeft > 0)
.listen((event) {
print(_secondsLeft.toString());
--_secondsLeft;
}, onDone: () {
print("It's show time!");
});
}
You are very close, you just need to only play the song when the timer has counted down, at the same time you cancel the timer.
So:
Timer? _timer;
void onPlay() async {
int _secondsLeft = 5;
_timer = await Timer.periodic(const Duration(seconds: 1), (_) {
if (_secondsLeft == 0) {
_timer?.cancel();
audio.play(_curSong);
} else {
_textToSpeech.speak(_secondsLeft.toString());
--_secondsLeft;
}
});
}
(Notice that this doesn't say zero, where your original did. Instead it plays the music. If you want it to say zero, change the == 0 to < 0.)
With this way of writing it, canceling the timer stops you from playing the song.

MQL4 Listenting to Candle Bar Open event

I am really new to MQL4, and still trying to grasp the concept. I would want to have an event handler to detect every candle bar opening (or every previous candle bar closing). Trying to wrap that around my head but it is not working:
So I have a function to check for the tick:
bool checkingFirstTick(){
datetime currentTime = iTime(Symbol(), Period(), 0);
if(currentTime - lastCandle > 0){
lastCandle = currentTime;
return true;
}
return false;
}
where lastCandle is a global variable.
Now when I put it into the OnTick() event:
void OnTick(){
Print("Ticking");
if(checkingFirstTick()){
Print("It's an opening!");
}
}
The It's an opening! statement never get printed.
Am I doing something fundamentally wrong? Or is there any more efficient way to listen to an opening of the candle bar, no matter what is the period I set?
Try this:
// --- Global Variable ----
datetime ArrayTime[], LastTime;
void OnTick() {
if(NewBar(PERIOD_H1)) {
// insert your program here
}
}
bool NewBar(int period) {
bool firstRun = false, newBar = false;
ArraySetAsSeries(ArrayTime,true);
CopyTime(Symbol(),period,0,2,ArrayTime);
if(LastTime == 0) firstRun = true;
if(ArrayTime[0] > LastTime) {
if(firstRun == false) newBar = true;
LastTime = ArrayTime[0];
}
return newBar;
}

Task with infinite cycle

I'm new in C#, I've gone to it from Delphi. So may be I do something wrong. My app (windows service) make tasks to control on-off states and count "on" time. I've tried to use Task.Delay(x), but it seems I catch deadlocks...
Main idea make tasks with infinite cycle which performs every x ms. I don't know if I could use the Timer for executing part code in lambda method of task...?
int TagCnt = DataCtrl.TagList.Count;
stopExec = false;
if (TagCnt != 0)
{
tasks = new Task[TagCnt];
for (int i = 0; i <= TagCnt - 1; i++)
{
int TempID = i;
tasks[TempID] = Task.Run(async () => // make threads for parallel read-write tasks // async
{
Random rand = new Random();
TimeSpan delay = TimeSpan.FromMilliseconds(rand.Next(1000, 1500))
try
{
while (!stopExec)
{
cToken.ThrowIfCancellationRequested();
//do basic job here
await Task.Delay(delay, cToken);
}//while end
}
catch (...)
{
...
}
}, cToken);
}
A couple of things went wrong here:
The tasks you're creating are completed instantly, in your case Task.Factory.StartNew returns Task<Task> because of the async lambda. To make it work as expected, unwrap the inner task with Task.Unwrap. Also, remove TaskCreationOptions.LongRunning, you don't need it here:
tasks[TempID] = Task.Factory.StartNew(async () => { ...}).Unwrap();
Alternatively, use Task.Run, it unwraps automatically (more about this):
tasks[TempID] = Task.Run(async () => { ...});
Besides, there's no synchronization context installed on a Windows service thread by default. Thus, the code after await Task.Delay() will be executing on a new pool thread each time, you should be ready for this.
Task.Delay is a bit different from a periodic timer. It will delay the execution. Use Stopwatch to calculate how much to delay for:
// beginning of the loop
stopwatch.Reset();
stopwatch.Start();
// the loop body
// ...
// end of the loop
await Task.Delay(Math.Max(500-Stopwatch.ElapsedMilliseconds, 0));

numberofactions on a node always returns 1 in cocos2d 2.1

Below sample code never come out of while loop and its printing the number of running actions as 1 always. What I am missing?
Thanks in advance
Krishna
-(id)init
{
if(self == [super init])
{
CCSPrite *mySprt = [CCSprite spriteWithFile:#"myFile.png"];
mySprt.position = ccp(160,240);
mySprt.tag = 331;
CCFadeTo *fadeSprt = [CCFadeTo actionWithDuration:20.0 opacity:0];
[mySprt runAction:fadeSprt];
[self addChild:mySprt];
[self checkActionCount];
}
return self;
}
-(void)checkActionCount
{
while([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(#"Number of actions = %d",[self getchildByTag:331].numberofrunningactions);
continue;
}
NSLog(#"Number of actions = %d",[self getchildByTag:331].numberofrunningactions);
}
You have an endless loop:
while([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(..);
continue;
}
The continue statement will exit the current block to re-evaluate the while condition, which is true, which will do a continue, and re-evaluate the while condition, and so on for all eternity.
Instead try this:
if ([self getchildByTag:331].numberofrunningactions > 0)
{
NSLog(..);
}
and call the checkActionCount method from a scheduled selector, for instace update:, so that the condition is evaluated once every frame.
CCFadeTo *fadeSprt = [CCFadeTo actionWithDuration:20.0 opacity:0];
[mySprt runAction:fadeSprt];
You initialize a CCAction with duration 20.0 seconds.
Now you run it on the mySprt. this increase the numberofRunningActions count by 1.
which is what you are checking in while loop and it logs 1.
After 20 seconds when the action finishes. it will log 0 (unless you add other action).

How to wait for 3 seconds in ActionScript 2 or 3?

Is there any way to implement waiting for, say, 3 seconds in ActionScript, but to stay within same function? I have looked setInterval, setTimeOut and similar functions, but what I really need is this:
public function foo(param1, param2, param3) {
//do something here
//wait for 3 seconds
//3 seconds have passed, now do something more
}
In case you wonder why I need this - it is a legal requirement, and no, I can't change it.
Use the Timer to call a function after 3 seconds.
var timer:Timer = new Timer(3000);
timer.addEventListener(TimerEvent.TIMER, callback); // will call callback()
timer.start();
To do this properly, you should create the timer as an instance variable so you can remove the listener and the timer instance when the function is called, to avoid leaks.
class Test {
private var timer:Timer = new Timer(3000);
public function foo(param1:int, param2:int, param3:int):void {
// do something here
timer.addEventListener(TimerEvent.TIMER, fooPartTwo);
timer.start();
}
private function fooPartTwo(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, fooPartTwo);
timer = null;
// 3 seconds have passed, now do something more
}
}
You could also use another function inside your foo function and retain scope, so you don't need to pass variables around.
function foo(param1:int, param2:int, param3:int):void {
var x:int = 2; // you can use variables as you would normally
// do something here
var timer:Timer = new Timer(3000);
var afterWaiting:Function = function(event:TimerEvent):void {
timer.removeEventListener(TimerEvent.TIMER, afterWaiting);
timer = null;
// 3 seconds have passed, now do something more
// the scope is retained and you can still refer to the variables you
// used earlier
x += 2;
}
timer.addEventListener(TimerEvent.TIMER, afterWaiting);
timer.start();
}
For AS3 use Radu's answer.
For AS2 use the setInterval function like so:
var timer = setInterval(function, 3000, param1, param2);
function (param1, param2) {
// your function here
clearInterval(timer);
}
You can also use delayedCall, from TweenMax. IMHO, it's the sharpest way to do that if you are familiar to TweenMax family.
TweenMax.delayedCall(1, myFunction, ["param1", 2]);
function myFunction(param1:String, param2:Number):void
{
trace("called myFunction and passed params: " + param1 + ", " + param2);
}
In your case, using a anonymous function:
public function foo(param1, param2, param3) {
//do something here
trace("I gonna wait 3 seconds");
TweenMax.delayedCall(3, function()
{
trace("3 seconds have passed");
});
}
why you are doing some confused ways instead of doing the right way?
there is a method named:"setTimeout()";
setTimeout(myFunction,3000);
myFunction is the function you want to call after the period.and 3000 is the period you want to wait(as miliseconds).
you don't need to set then clear interval, or make a timer with one repeat count or do sth else with more trouble☺.
There is no Sleep in ActionScript. But there are other ways to achieve the same thing without having all your code in a single function and wait within that function a specific amount of time.
You can easily have your code in two functions and call the 2nd one after a specific timeout you set in your 1st function.
THIS IS NOT WITHIN ONE FUNCTION - ANSWERS: "How to wait for X seconds in AS2 & 3"
...without using setInterval or clearInterval.
The answers posted above are much faster and easier to use. I posted this here, just in case...
Sometimes you may not be able to use set/clearInterval or other methods based on development restrictions. Here is a way to make a delay happen without using those methods.
AS2 - If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
I have an onEnterFrame countdown timer in here as well, (demos stopping/switching timers).
If you want the delay/glow to be longer - increase the glowGameTime number. Change the names to fit your own needs and/or apply the logic differently.
var startTime:Number = 0;
var currentTime:Number = 0;
var mainTime:Number = 5;//"game" time on enter frame
var glowStartTime:Number = 0;
var glowCurrentTime:Number = 0;
var glowGameTime:Number = 1.8;//"delayed" time on press
btnGlowTest._visible = false;
this.onEnterFrame = TimerFunction;
startTime = getTimer();
function TimerFunction()
{
currentTime = getTimer();
var timeLeft:Number = mainTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up...3 bucks off");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
function glowTimerFunction()
{
glowCurrentTime = getTimer();
var glowTimeLeft:Number = glowGameTime - ((glowCurrentTime - glowStartTime)/1000);
glowTimeLeft = Math.floor(glowTimeLeft);
//trace("glowTimeleft = " + glowTimeLeft);
if(glowTimeLeft <= 0)
{
trace("TIME DELAY COMPLETE!");
//...do stuff here
btnGlowTest._visible = false;//just for show
btnTest._visible = false;//just for show
StopTime();
}
}
btnTest.onPress = function()
{
trace("onPress");
btnGlowTest._visible = true;
StopTime();
GlowTime();
}
function GlowTime()
{
trace("GlowTime Function");
this.onEnterFrame = glowTimerFunction;
glowStartTime = getTimer();
}
function StopTime()
{
trace(">>--StopTime--<<");
delete this.onEnterFrame;
}
AS3 - Below is the code from above setup to run in AS3. There are different ways to accomplish similar results, yet based on the project scope, these are the methods that were used in order to get things functioning properly.
If you copy/paste the code below to your timeline, make sure to add two movie clips to the stage, btnTest and btnGlowTest (include like instance names). Make "btnGlowTest" larger, a different color, & behind "btnTest" (to simulate a glow and a button, respectively).
Compile and check the output panel for the trace statements to see how the code is working. Click on btnTest - btnGlowTest will then become visible throughout the duration of the delay, (just for visual representation).
If you want the delay/glow to be longer - increase the GlowTimer:Timer number, (currently set to 950). Change the names to fit your own needs and/or apply the logic differently.
import flash.events.MouseEvent;
import flash.utils.Timer;
import flash.events.TimerEvent;
var startTime:Number = 0;
var currentTime:Number = 0;
var gameTime:Number = 4;//"game" time on enter frame
var GlowTimer:Timer = new Timer(950,0);//"delayed" time on press
btnGlowTest.visible = false;
GlowTimer.addEventListener(TimerEvent.TIMER, GlowTimeListener, false, 0, true);
btnTest.addEventListener(MouseEvent.MOUSE_DOWN, btnTestPressed, false, 0, true);
addEventListener(Event.ENTER_FRAME,TimerFunction, false, 0, true);
startTime = getTimer();
function TimerFunction(event:Event)
{
currentTime = getTimer();
var timeLeft:Number = gameTime - ((currentTime - startTime)/1000);
timeLeft = Math.floor(timeLeft);
trace("timeLeft = " + timeLeft);
if(timeLeft <= 0)
{
trace("time's up, 3 bucks off");
StopTime();
}
}
function GlowTimeListener (e:TimerEvent):void
{
trace("TIME DELAY COMPLETE!");
StopTime();
}
function btnTestPressed(e:MouseEvent)
{
trace("PRESSED");
removeEventListener(Event.ENTER_FRAME, TimerFunction);
btnGlowTest.visible = true;
GlowTimer.start();
}
function StopTime()
{
trace(">>--Stop Time--<<");
btnGlowTest.visible = false;//just for show
btnTest.visible = false;//just for show
GlowTimer.stop();
removeEventListener(TimerEvent.TIMER, GlowTimeListener);
removeEventListener(Event.ENTER_FRAME, TimerFunction);
}

Resources