How to use a signal as function parameter in CAPL - function

I am trying to write a function in CAPL that takes a signal and calculates the physical value with the signal value, the signal factor and the signal offset.
This is how a simple gateway normally works:
message CAN1.myMessage1 myMessage1 = {DIR = RX};//message from the database
message CAN2.myMessage2 myMessage2 = {DIR = TX};//another message from the database
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = myMessage1.mySignalA * myMessage1.mySignalA.factor + myMessage1.mySignalA.offset;
}
}
And this is what I am trying to do:
...
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(myMessage1.mySignalA);
}
}
double PhysicalValue(signal * s)
{
return s*s.factor+s.offset;
}
There are two problems with this code:
Firstly when I pass the signal as the parameter the compiler says that the types don't match. The second problem is that inside the function the attributes (factor and offset) are no longer recognized.
These problems might have something to do with the weird object-oriented-but-not-really nature of CAPL. The value of the signals can be accessed directly but it also has attributes?
int rawValue = myMessage1.mySignalA;
If you are familiar with C you might say that the problem is that I am specifying a pointer in the function but that I am not passing a pointer into it. But in CAPL there are no pointers and the * simply means anything.
Without the * I would have needed to use a specific signal which would have defeated the purpose of the function.
EDIT:
I have found the attribute .phys by now which does exactly what my demo function would have done.
double physValue = myMessage1.mySignalA.phys;
This has already made my code much shorter but there are other operations that I need to perform for multiple signals so being able to use signals as a function parameter would still be useful.

What you can do is this:
double PhysicalValue(signal * s)
{
// access signal by prepending a $
return $s.phys;
}
Call like this
on message CAN1.*
{
if(this.id ==myMessage1.id)
{
myMessage1 = this;
myMessage2.mySignalB = PhysicalValue(CAN1::myMessage1::mySignalA);
}
}
I.e. when you call your function, you have to provide the qualified name of the signal (with colons rather than dots). To my knowledge it is not possible to use myMessage1.mySignalA, since signals itself are not a CAPL datatype.
Apart from this, you might re-think whether you really should be using on message, but rather switch to on signal. Handling the signal values no matter with which message they are sent is done by CANoe's signal server.

Note that CANoe already has a function which does exactly what you're trying to do (multiplying by factor and adding offset). It's called getSignal:
on message CAN1.*
{
if(this.id == myMessage1.id)
{
myMessage2.mySignalB = getSignal(myMessage1::mySignalA);
}
}
Offsets and factors are defined in e.g. the DBC files.

Related

Node-red - need a multi-input function for a number value

So I'm just getting to grips with node-red and I need to create a conditional global function.
I have two separate global.payloads set to a number value of either 0 or 1.
What I need to happen now is, if global.payload is equal to value 1 then follow this flow, if it is equal to value 0 then follow this one.
I'm just a little confused with the syntax for the function statement. Any help gratefully appreciated.
Since you haven't accepted the current answer, thought I'd give this a try.
I think this is what you need to handle inputs from two separate global contexts. I'm simulating them here with two separate inject nodes to demonstrate:
The checkconf inject node emits a 1 or a 0. Same for the meshstatus node. Substitute your real inputs for those inject nodes. The real work is done inside the function:
var c = context.get('c') || 0; // initialize variables
var m = context.get('m') || 0;
if (msg.topic == "checkconf") // update context based on topic of input
{
c = {payload: msg.payload};
context.set("c", c); // save last value in local context
}
if (msg.topic == 'meshstatus') // same here
{
m = {payload: msg.payload};
context.set('m', m); // save last value in local context
}
// now do the test to see if both inputs are triggered...
if (m.payload == 1) // check last value of meshstatus first
{
if (c.payload == 1) // now check last value of checkconf
return {topic:'value', payload: "YES"};
}
else
return {topic:'value', payload: "NO"};
Be sure to set the "topic" property of whatever you use as inputs so the if statements can discriminate between the two input. Good luck!
You can use the Switch node to do this, rather than a Function node.

Call a function if String number is inferior to 0?

I've got this code in my Toolbar.as :
var money = 9999;
argent.text = String(money);
trace(money);
How do I do to say
if (money < 0){
callFunction();
}
?
Thank you very much for your answers
EDIT
I've tried everything.
Here's what I did :
var money:int = 9999;
argent.text = money.toString();
trace(money);
stageRef.addEventListener("checkingMoney", checkMoney, false, 0, true);
I've add the EventListner in order to check the money (as nothing was triggering the condition if money<0 before).
And then :
public function checkMoney(event):void{
var money;
trace("checking");
if (parseInt(money) < 0){
trace("dangerous");
}
}
So the function is well triggered (the trace "checking" is on), but even the number is under 0 (-4600), the trace "dangerous" do NOT appear..
I don't understand.
You need to read up on how datatyping works. It works similarly in all OOP-based languages, so an AS3-specific article really isn't necessary. Avoid anything regarding PHP datatypes, though.
For what you have posted, though, you have done a few things incorrectly.
First off, every object (whether it be a variable, function, or class), should always have the datatype declared. You can get away with not doing it, but your app will run slightly faster if you do and there is less chance of compiler warnings.
So
var money = 9999;
should be
var money:int = 9999; // could also use Number (AS3's float) or uint
You should avoid hard-casts such as String(money), as well. This can be slow and can cause errors. For casting a Number to a String, you should always use Number.toString(), as that is its intended purpose and I believe it is optimized whereas other cast types are not.
if (money < 0) is actually correct. It may have been throwing IDE warnings because you didn't set the type of money. If you need to compare a numeric String value, you need to cast it back to a number using Number(var). Note that casting a String to Number is one of the few times you want to use a hard cast DataType(object) instead of a soft cast (object as DataType).
I don't get the problem.
1st of all money variable is missing a type.
If money is int here than:
var money:int = 9999;
argent.text = money.toString();
trace(money);
if (money < 0){
callFunction();
}
and that should work.
If for some reason money is String in here than:
var money:String = "9999";
argent.text = money;
trace(money);
if (Number(money) < 0){
callFunction();
}
I don't usually do this, but I'm posting a second answer because your edit is drastically different than what you originally posted. For future reference, please post the entire code that is relevant. You seemed to have missed some context originally and forced us to solve the wrong problem (don't get me wrong, it still needed to be fixed but it was not the issue at hand)
So what you are seeing is a scope issue. Basically, an object declared in an object (be it a Class, Function, loop, or conditional) is only available within that object and within child objects. Additionally, all objects declared in the top-level scope of a class must have an access modifier (public, private, internal, protected, etc).
So let's assume this class structure:
public class ClassName {
public function ClassName();
public function checkMoney();
}
An object declared in the constructor (ClassName()) is not available in checkMoney(). So you need to do one of two things:
Declare the object in top-level scope:
public class ClassName {
private var money:int;
public function ClassName(){
money = 9999;
checkMoney()
}
public function checkMoney() {
// you now have access to money
}
}
or pass the object into the function:
public class ClassName {
public function ClassName(){
var money:int = 9999;
checkMoney(money);
}
public function checkMoney(value:Number) {
// check "value" here. Note that Numbers and Strings are NOT passed be reference, so changing the value will NOT change the original variable
}
}

How to find specific value in a large object in node.js?

Actually I've parsed a website using htmlparser and I would like to find a specific value inside the parsed object, for example, a string "$199", and keep tracking that element(by periodic parsing) to see the value is still "$199" or has changed.
And after some painful stupid searching using my eyes, I found the that string is located at somewhere like this:
price = handler.dom[3].children[3].children[3].children[5].children[1].
children[3].children[3].children[5].children[0].children[0].raw;
So I'd like to know whether there are methods which are less painful? Thanks!
A tree based recursive search would probably be easiest to get the node you're interested in.
I've not used htmlparser and the documentation seems a little thin, so this is just an example to get you started and is not tested:
function getElement(el,val) {
if (el.children && el.children.length > 0) {
for (var i = 0, l = el.children.length; i<l; i++) {
var r = getElement(el.children[i],val);
if (r) return r;
}
} else {
if (el.raw == val) {
return el;
}
}
return null;
}
Call getElement(handler.dom[3],'$199') and it'll go through all the children recursively until it finds an element without an children and then compares it's raw value with '$199'. Note this is a straight comparison, you might want to swap this for a regexp or similar?

Custom sorting function bottleneck

I am trying to sort big array using actionscript 3.
The problem is that i have to use custom sorting function which is painfully slow and leads to flash plugin crash.
Below is a sample code for custom function used to sort array by length of its members:
private function sortByLength():int {
var x:int = arguments[0].length;
var y:int = arguments[1].length;
if (x > y){
return 1;
}else if (x < y){
return -1;
}else{
return 0;
}
}
Which is called like this:
var txt:Array = ["abcde","ab","abc","a"];
txt.sort(sortByLength);
Please advise me how can this be done faster ?
How to change application logic to avoid Flash plugin crashes during sorting ?
try to use strong typing whenever possible, here tell your function that you are waiting two strings.
you could rewrite your function in two way one fastest than the other if you know that all your element are not null:
function sortByLength(a:String, b:String):int {
return a.length-b.length // fastest way not comparison
}
and if you can have null check for it (this one will put null in front of all element):
function sortByLengthWithNull(a:String, b:String):int {
if (a==null) return -1
if (b==null) return 1
return a.length-b.length
}
If you need super-fast sorting, then it might be worthwhile not using an array at all and instead using a linked-list. There are different advantages to each. Primarily, with a linked-list, index-access is slow, while iterating through the list is fast, and linked-lists are not native to AS3 so you'll have to roll your own.
On the upside, you may well be able to use some of Polygonal Labs' code: http://lab.polygonal.de/as3ds/.
Sorting is very, very fast for nearly-sorted data with a linked list, as this article discusses: http://lab.polygonal.de/2007/11/26/data-structures-more-on-linked-lists/.
This solution gives you lots more work, but will eventually give you lots more sort-speed too.
Hope this helps.
-- additional --
I noticed your question in the comments of another answer about "One question however is unanswered - how to perform greedy computations in Flash without hanging it?"
For this, essentially the answer is to break your computation over multiple frames, something like this:
public function sort():void
{
addEventListener(Event.ENTER_FRAME, iterateSort);
}
private function iterateSort():void
{
var time:int = getTimer() + TARGET_MILLISECONDS_PER_FRAME;
var isFinished:Boolean = false;
while (!isFinished && getTimer() < time)
isFinished = continueSort();
if (isFinished)
removeEventListener(Event.ENTER_FRAME, iterateSort);
}
function continueSort():Boolean
{
... implement an 'atom of sort' here, whatever that means ...
}
sortByLength should have two parameters, shouldn't it? I guess that's what you mean by the arguments array...
This looks fine to me, unless arguments is not a local variable, but instead a member variable, and you're just looking at its [0] and [1] elements on each function call. That would at least produce undesired results.

LINQ-to-SQL oddity with multiple where clause arguments on the same field

My problem requires me to dynamically add where clauses to a IQueryable based on user input. The problem i'm having is that Linq-to-SQL doesn't seem to like having multiple where clauses on the same field, it actually duplicates the search arg value for the last item on all parameters. I verified this behavior through a SQL trace. Here is what I'm seeing.
WHERE ([t22].[OpenText] LIKE #p11) AND ([t22].[OpenText] LIKE #p12)
-- #p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%] // Should be 2da57652-dcdf-4cc8-99db-436c15e5ef50
-- #p12: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%]
My code uses a loop to dynamically add the where clauses as you can see below. My question is how do I work around this? This pretty much seems like a bug with the tool, no?
// add dyanmic where clauses based on user input.
MatchCollection searchTokens = Helper.ExtractTokensWithinBracePairs(filterText);
if (searchTokens.Count > 0)
{
foreach(Match searchToken in searchTokens)
query = query.Where((material => material.OpenText.Contains(searchToken.Value)));
}
else
{
query = query.Where((material => material.OpenText.Contains(filterText)));
}
Closing over the loop variable considered harmful! Change
foreach(Match searchToken in searchTokens) {
query = query.Where(
material => material.OpenText.Contains(searchToken.Value)
);
}
to
foreach(Match searchToken in searchTokens) {
Match token = searchToken;
query = query.Where(
material => material.OpenText.Contains(token.Value)
);
}
You are closing over the loop variable, which is considered harmful. To fix do this:
foreach(Match searchToken in searchTokens)
{
Match searchToken2 = searchToken;
// ^^^^^^^^^^^^ copy the value of the reference to a local variable.
query = query.Where(material => material.OpenText.Contains(searchToken2.Value));
// use the copy here ^^^^^^^^^^^^
}
The reason why your version doesn't work is that the query refers to the variable searchToken, not the value it had when the query was created. When the variable's value changes, all your queries see the new value.
I don't have enough rep to leave comments yet (or this would be a comment and not an answer) but the answers listed here worked for me.
However, I had to turn off compiler optimizations in order for it to work. If you do not turn off compiler optimizations (at least at the method level) then the compiler sees you setting a loop variable to a local variable and throws the local variable away.