CAPL Code to send signal value from a button - capl

I am using CANoe 11.0 to send a signal value from a button.
I have a message from a CAN db with 6 signals, 8 bits for each signal. The message is cyclic but with a cycle time of 0ms, so, in order to send it, I figured out I need a button. But everything I tried so far doesn't work.
eg:
on message X
{
if (getValue(ev_button) == 1)
{
X.signalname = (getValue(ev_signalvariable));
}
}
or I tried working on the signal itself:
on signal Y
{
if (getValue(ev_button) == 1)
{
putValue(ev_signalY,this);
}
}

The issue you are having is due to the callback. Both on message and on signal callbacks happen when that message or signal is updated on the bus.
In your code, you expect to update a signal, if you pressed a button, but only if you detect that signal was updated in the first place. Do you see the loophole?
To fix this, you may create a system variable, associate that with the button (so that it is 0 = not pressed and 1 = pressed), then use the on sysvar callback:
on sysvar buttonPressed
{
// prepare message
// send message
}
I assume you already have something like message yourMessage somewhere, and that you know the name of the signal from the DBC and that the DBC is linked to your configuration. So you'll need to:
// prepare message
yourMessage.yourValue1 = <some value>
yourMessage.yourValue2 = <some other value>
// ...
// repeat for all relevant signals
and then
// send message
send(yourMessage)

Related

How to fetch multiple SM which were received after single CM request karate websocket

def socket = karate.webSocket(demoBaseUrlgame)
def body = {"_id":"p194","pid":1960939,"at":'#(gsauthtoken2)',"f1":'#(gametableid)',"f2":"023e86a7-d579-33a4-ac4f-9803beecaef1","f3":"webh5","f4":false,"f5":"","f6":"","f7":"","f8":"Windows","f9":"10","f10":"Chrome","f11":"96.0.4664.110","f12":false,"f13":"","f14":"","f15":false}
print "Body:", body
socket.send( '#(body)')
def loginuser2 = socket.listen(1000)
print loginuser2
In this one, i am sending one CM request but getting multiple SM, but only first one is getting fetched with or without the handler.
Is there a way where we can fetch multiple sm for one cm?
If you want to "gather" multiple messages, you need to write a "handler" function with logic to "stop" when you have enough messages.
This is covered in the example, please read the docs: https://github.com/karatelabs/karate#websocket
I'm showing the line in the example which you should study carefully below:
* def handler = function(msg){ return msg.startsWith('hello') }
So you can do anything, for example wait until some particular message, wait until some elapsed time, or wait until some count of messages. How you write that logic is up to you and your messages.

How to insert an "on key" Replay block in CAPL

I'm wondering if it is possible to create a CAPL code in which, by using "on key" feature, the user may:
- activate a replay mode (.asc file)
- activate a filter on it
- activate additionally a specific signal (not present in asc files)
- deactivate the replay mode
- deactivate the specific signal
- activate or deactivate alternatively specific messages and/or trace
In detail, for the moment I am using this one:
/*#!Encoding:1252*/
variables // declaration of the specific messages I need
{
message MESSAGE01 msg_MESSAGE01 ;
message MESSAGE02 msg_MESSAGE02 ;
}
on key 't' // here I'd need the activation of a replay block in .asc format with a filter on a specific message
{
// Really don't know how to insert here
}
on key 'd' // here I'd need the deactivation of a replay block in .asc format
{
// Really don't know how to insert here
}
on key 'p' // specific signals deactivation
{
msg_MESSAGE01.SIGNAL01= 0; // assign the value to the message
msg_MESSAGE02.SIGNAL02 = 1; // assign the value to the message
output(msg_MESSAGE01); //send the message to the CAN bus
output(msg_MESSAGE02); //send the message to the CAN bus
// output(output of the asc file); // if activated, I'd like to see in output all the messages of the .asc; if not, I'd like to see just those specific signals.
}
on key 'u' // specific signals deactivation
{
// msg_MESSAGE01.SIGNAL01 = none; // here, I'd like to "unset" the value
msg_MESSAGE02.SIGNAL02= 0;
output(msg_MESSAGE01);
output (msg_MESSAGE02);
// output(output of the asc file); // if activated, I'd like to see in output all the messages of the .asc; if not, I'd like to see just those specific signals.
}
If not clear, I'm available to explain better my request :)
Thank you in advance ^^
Cheers
Welcome to StackOverflow!
You can actually activate a replay block (at least on CANoe, please have a look for compatibility on CANalyzer).
I'd need the activation/deactivation of a replay block in .asc format
variables
{
char replayName[32] = "ibus_data";
}
on key 'b'
{
replayStart( replayName);
}
on key 'e'
{
replayStop( replayName);
}
on key 's'
{
replaySuspend( replayName);
}
on key 'r'
{
replayResume( replayName);
}
on key 'w'
{
writeReplayState( replayName);
}
void writeReplayState( char name[])
{
switch ( replayState( name))
{
case 0:
write( "Replay Block %s is stopped", replayName);
break;
case 1:
write( "Replay Block %s is running", replayName);
break;
case 2:
write( "Replay Block %s is suspended", replayName);
break;
default:
write( "Error: Replay Block %s has an unknown state!", replayName);
break;
};
}
You'll have to configure the replay file beforehands, and the filter part requires a different solution. For more information, check the reference and this example: ReplayStart, ReplayStop, ReplaySuspend, ReplayResume, ReplayState
From: CAPL Function Overview » General » Example: ReplayStart, ReplayStop, ReplaySuspend, ReplayResume, ReplayState
specific signals activation/deactivation
One "hacky" solution that pops into my mind, it to have a flag system in place. Of course, ugly solution, probably there is something better at hand. Try something like:
on message myMessage
{
if (flag)
output(myMessage)
}
on key 'u'
{
flag ? 0 : 1 // short for: toggle the status of the flag
}
Please let me know if this helped.
Regarding this piece of code:
on key 'p' // specific signals deactivation
{
msg_MESSAGE01.SIGNAL01= 0; // assign the value to the message
msg_MESSAGE02.SIGNAL02 = 1; // assign the value to the message
output(msg_MESSAGE01); //send the message to the CAN bus
output(msg_MESSAGE02); //send the message to the CAN bus
}
Please note that it won't do what you expect. You are asking to send the message on user keyboard action. If the message was already set for cyclic output, it will continue to go with the clock and an extra publish will be made on keyboard. Otherwise, message will only be published once.
The proposed solution works with a flag in the on message *, that, in turn, works as a filter, blocking the message and repeating it only if the flag is set.
You can just add Replay Block to the bus, and in configuration type specified start/stop key. Specified signals activation/deactivation can stay as you wrote it.

Rule of thumb for designing protocol messages

I have a very simple music player, and I'd like to make it into a music server.
I plan in using gRPC to communicate between the clients and the server.
However, I'm not sure how I should design the protocol messages to handle the playback.
I envision two types of design :
A message for each type of query. This method defines clearly all possible actions, but seems to create a lot of redundant code.
message Play{
bool flag = 1; // False means Pause
}
message Stop{
bool flag = 1;
}
A unique message, with a key containing the action. This approach seems more flexible, but also more prone to errors. I could use an enum object to limits the possible actions though.
message Playback{
enum Action {
PLAY = 0;
STOP = 1;
}
Action action = 1;
}
Basically, I guess that what's I'm asking here is whether I should define an action by the type of the message or by its content.
Is there a rule of thumb or a design pattern to apply here ?
I would recommend to use the oneof construct here:
syntax = "proto3";
message Play {
}
message Stop {
}
message Command {
oneof command {
Play play = 1;
Stop stop = 2;
...
}
}
Empty messages are fine when there are no parameters that you need to pass, and this also leaves open an easy way to extend the messages in the future, for example changing Play to:
message Play {
string filename = 1;
}
would allow including an optional filename with the request, while retaining compatibility with the old version.

Send Message/ Inject a message with CAPL

I am new in CANoe, and also CAPL language. But I want to ask you:
How can I send a message with CAPL on the network of ECU's. For example: I want to send an Hex number( it is a question for an ECU) and after that I want to see the response of this question.
I don't know if I was very clear but, if you have any answers I would be grateful.
Sending message in CAPL
You can send a message (or multiple messages) on any event,
for example, a keypress, the reception of another message, the reception of an error frame, or a timer expiring.
Sending an event message involves creating an event procedure, declaring a message to send, and sending the message in the event procedure.
The message can be declared as a global variable so that it can be accessed in any event procedure.
As shown in the message object section, you can declare a message’s structure in your program or you can use an associated database.
In this example, we will declare one of each in the Global Variables window
variables
{
message EngineData msg1; // Defined in database
message 0x101 msg2; // Standard message 101 (hex)
message 0x105x msg3; // Extended message 105 (hex)
}
Now, to send a message, we only need to put one of these lines into an event procedure:
output(msg1);
output(msg2);
Of course, we can also add data to the message before we send it.
The EngineData message has signals defined in the database, but the other message does not. Therefore, we have to use two different methods to add data to the messages.
msg1.EngSpeed.phys = 1000;
msg1.EngTemp.phys = 150;
msg1.IdleRunning = 1;
output(msg1);
msg2.DLC = 4; // Allocate 4 data bytes in msg2
msg2.byte(0) = 0x16; // First word is 16 hex
msg2.byte(1) = 7; // Second word is 7 decimal
output(msg2);
Responding Message
on message 0x101 // This is the identifier of your response
{
if(this.byte(0) == 0x16)
{
write("Response is the expected!");
}
}
or
on message msg2 // This is the identifier of your response
{
if(this.byte(0) == 0x16)
{
write("Response is the expected!");
}
}
You can use as given below,
variables
{
message BCMmsg01 msg_BCMmsg01; // declaration of message into a variable
}
on key 'z'
{
msg_BCMmsg01.C_AutoLockCmd = 3; // assign the value to the message
output(msg_BCMmsg01); //send the message to the CAN bus
}
Hopefully I clarified your question. Let me know if you need more clarification.
Joe showed the way the message (in this case the hex value) is sent. If you want to see the response, you need to know the response ID (for example 0x62C)
on message 0x62C /* This is the identifier of your response */
{
if(this.byte(X) == 0xYY) { /* X is the byte of the response you are interested and Y the value of that byte*/
write("Response is the expected!");
}
I hope this answers your question.

not receiving '>' after using at+cmgs

I am using SIM900 GSM module connect to my AVR microcontroller.My compiler is Code Vision AVR.
I want to send a message and I don’t want to use delay.I use an usart rx interrupt. I want to receive '>' in rx interrupt after sending number.Then send my meessage.
But '>' charachter wasn’t received. I am checking this process with a 'a' variable. First of all 'a' variable is equal to zero and after 1 minute is equal to 2. But it is never equal to 3. As a result my message haven't been sent. I can't find my problem!
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index++]=data;
if(a==2)
{
if(data=='>')
a=3;
}
#if RX_BUFFER_SIZE == 256
// special case for receiver buffer size=256
if (++rx_counter == 0)
{
#else
if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
#endif
rx_buffer_overflow=1;
}
}
}
void main()
{
//...rest of code
printf("at+cmgf=1%1c",enter);
printf("at+cmgda=%1c%s%1c%1c",q,del,q,enter);
while (1)
{
//...rest of code
RTC();
if(minute!=1*count)
flag1=0;
if(minute==1*count && flag1!=1)
{
flag1=1;
count++;
a=1;
}
if(a==1)
{
printf("at+cmgs=%1c%s%1c%1c",q,tel,q,enter);
a=2;
}
if(a==3)
{
printf("Ba salam\rTemperature=%d\rHumidity=%d\rWind Direction=%s\rWind Speed=%d%1c%1c",temperature(),humidity(),direct1,anemometer(),cz,enter);
a=0;
}
}
}
You are not doing proper parsing of the responses from the modem.
First of all, never, ever, ever use time as a separator for command and response. You MUST read and parse everything received from the modem until you get a final response. Absolutely nothing else will work reliably. See this answer for some hints on how to fix.
And secondly, for AT+CMGS you MUST wait for a sequence of four characters, \r\n>, before sending data. There is also hints about this in the above linked answer.
You appear to be sending commands using lower case letters. The user manual specifies capital letters, that is, AT not at.
There is also something wrong with the minute-count code at the top of the loop. The flag1 will be set back to 0, which will eventually change a to 1 again, which will cause the message to be sent again. I don't think this is your immediate problem but it should be corrected.
We also don't know if the message is getting through to the SIM900. Maybe trying testing this by sending the AT commands over a terminal and checking the return values. (Your code doesn't check if the first two commands are acknowledged by the SIM900, for example.)
EDIT:
Looking more closely, I see that your code is not following the protocol set out in the manual for sending a text. This may be because the manual has a typographical error. It has two sections labelled "Sending a Text", but one of them is actually for reading a text.
You don't need to include the AT+CMGDA=”DEL ALL” part. This is in the section for reading a text. Also, you have misspelled ”DEL ALL” as "DElALL".
The bigger problem is that sending the two commands so close together is clobbering the return codes.

Resources