CAPL: Why am I not receiving the data bytes of a CAN message in CAPL? - can-bus

I have an ECU sending a CAN message with 2 bytes of data. I want to take those 2 data bytes in CAPL and put them into 2 environment variables. I am developing a canoe simulation and I want to use those 2 environment variables to display their value in a panel.
I am seeing the CAN message with the data bytes on trace being received correctly, but when I try using those data bytes in CAPL, they are 0.
I have the following code:
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, SWversion.MainSW);
putValue(ev_SecSW, SWversion.SecSW);
}
SWversion.MainSW is byte(0), SWversion.SecSW is byte(1). I see their values on trace, but in CAPL they are 0.
Any hints as to why?
Here's my trace window with the data bytes
Here's my message & signals definition in the database
Here's one of my variable definitions

In your event handler it seems that you should access the received message, not a global (obviously uninitialized) variable:
on message CAN1.SWversion
{
putValue(ev_MainSW, this.MainSW);
putValue(ev_SecSW, this.SecSW);
}

I figured it out:
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, SWversion.MainSW);
putValue(ev_SecSW, SWversion.SecSW);
}
needed to be changed to
message CAN1.SWversion SWversion;
on message SWversion
{
putValue(ev_MainSW, this.byte(0));
putValue(ev_SecSW, this.byte(1);
}
Apparently, you cannot use predefined signals to access the data in a CAN message in CAPL.

Related

Driver error 11 in TransmitCANFrame XL_ERR_QUEUE_IS_FULL

I am using a CANCase VN1640A between 2 ECUs in order to falsify a CAN message. Below the bridge simulation setup:
In my CAPL Code, the received messages from channel 1 will be redirected to channel 3 and vice-versa. (So far I am not falsifying any message)
variables{
message can1. msgCAN1;
message can3. msgCAN3;
}
on message can1.{
msgCAN3=this;
if(this.dir == rx)
output(msgCAN3);
}
on message can3.{
msgCAN1 = this;
if(this.dir == rx)
output(msgCAN1);
}
But when I start CANoe I get this Error message:
This error means that CANoe tries to send more as it could. The transmit buffer is overflowed. I have changed the hardware configuration of Transmit Queue size to the max 32768 messages, also the Receive Latency to very fast but unfortunately the error occur again.
Does anyone have any hints that could help to solve this problem and thanks in advance.
The error message can mean, that CANoe tries to send more as it could. The transmit buffer is overflowed. This can have several causes:
the bus is full of high prior messages and therefore CAN hardware cannot send
You have a program which writes messages very quick to the buffer, so that the card canĀ“t send (while loops for).
Error frames occur when sending and thus the card cannot send.
Vector tool provides a loop test:
Send messages from CH1 to CH3. If this is working fine, it looks like the problem is caused by your CANoe configuration.
The necessary test programs are part of the Vector Driver Setup Files and located in the folder Common. You can download the Driver Setup File from www.vector.com/driver-setup.
CAN Highspeed Looptest: http://kb.vector.com/entry/589/
CAN Low-speed Looptest: http://kb.vector.com/entry/590/
If the loop test works fine, you can see the time, the busload etc. If not, you will get a failed message.
Note:
Reduce the number of channels used in CANoe/CANalyzer under:
Configuration | Options | Measurement | General | Channel usage.
Are there more selected channels in the CANoe configuration than assigned CANcabs in the Vector Hardware Config?
(Start | Control Panel | Hardware and Sound | Vector Hardware)
Please check the channel and application assignment in the Vector Hardware Config.
Kindly check the hardware mapping in CANoe. This error mostly arises when the mapping is not correct or disturbed.
Go to Hardware-> Network Hardware configuration -> Driver -> Select proper channel for the vector hardware
I hope this helps !
So this error does NOT mean that CANoe tries to send more as it could.
It means instead:
We have (many) error frames on the CAN bus. CANoe tries to send messages which does not work (for whatever reason) -> error frames are the result. The CAN controller will retry to send the frame which might again lead to an error frame. Now over time the Send Requests accumulate and lead to further error frames. At some point the buffer for the error frames does overflow which leads to the message you see in the write window.
Solution:
We have to check the Trace Window and check what kind of error frames we get there (and then take suitable measures to prevent them).

How to modify message data in CAPL if message is generated by Interactive generator block?

I am using CANalyzer.
I am transmitting CAN message using Interactive Generator block. I use IG to modify signals in transmitted message by hand.
I need to automaticaly calculate checksum (the last byte in the message) every time the message is sent. Checksum is calculated from all previous data bytes in the message (message is always 8 bytes long). There is no option in IG to do that.
I need:
Set signals by hand using IG.
Automatically calculate value of the last data byte according to values of preceding data bytes.
I tried to write simple code in CAPL but without success.
I put CAPL Program node after the IG node in the Configuration window and wrote on message event in CAPL script:
on message FooMsg
{
message FooMsg msg1; // FooMsg is name of message in database
msg1 = this; // copy message from IG to temporary variable
// this.byte(7) = 0x11; // not posibble, compiler warning
msg1.byte(7) = 0x11; // constant value just for test
output(msg1); // send message
}
The message is transmitting but the Tx period set in IG is not respected (message is transmitted as fast as possible).
I thought I catch the message generated from IG, modify it and send to CAN bus.
Finally, I redesigned the whole stuff as VioletVynil recommended.
I created panels, add system variables and hooked them to controls on panels, wrote some code in CAPL for calculating checksum and periodic transmit of the message and it runs! Without any problems! And yes additional CRC on the payload is used for additional safety (railway application). I didn't designed communication protocol, I just got it.

Sending cyclic message using CANoe - IL DLL

I have a configuration setup with two CAN nodes and an attached database. I have added a CANOEILNLVECTOR.dll to both the nodes. By adding this Dll file all my messages are sent cyclic as I see in trace window.
Now I set some value for a signal in a message, For Eg:
variables
{
message Battery_Traction Batt_msg;
}
on start
{
Batt_msg.Isolation_Signal = 0x02; //0x02:On
output(Batt_msg);
}
What I see on trace is: The message is cyclic but only for the first instance the value set by me above appears in trace. For all of the rest times the signal value in the message in set to default.
As seen in the image value 0x02 is sent only once.
I am not sure what could be the problem, as seen in image attached value set by me is only sent once.
When using output you are putting the message directly onto the CAN bus, but you are not changing the value inside of your (simulated) node, so the interaction layer is still sending the old value.
You can change the signal value in the interaction layer by just putting a $ in front of the signal name and set the value.
In your case most likely $Isolation_Signal = 0x02
Outputting the message on the CAN bus at the right time, with the right cycle time and so on will be handled by the interaction layer.
You have two ways to influence dynamically the value of your message: IL DLLs and custom message sending.
Custom message sending is the basic way, where
you define the message ex.: message Battery_Traction Batt_msg;
you trigger its sending(output function)
you set up cyclic sending on timer Cycletimemsg1 {output(msg1);}
and so on.
IL DLLs are doing this all for you, without much coding effort from your side, but they rely heavily on the dbc settings and attributes you have linked as database to your CAN Channel.
Unfortunately, they don't play well together, meaning you need advanced CANoe know-how of them to use both in the same environment. You basically bypassed your CANOEILNLVECTOR.dlls working by sending explicit message.
So your code if you are accessing your signal through IL, should look like this:
variables
{
/*no need to define custom message object, they are already "known" to IL by dbc*/
}
on start
{
$Batt_msg::Isolation_Signal = 0x02; //0x02:On
/*NO need for output either (IF YOUR MESSAGE IS defined Cyclic in dbc), */
}
If your signal is not identified at $Batt_msg::Isolation_Signal, just dragndrop the signal from the CAPL browsers Symbols panel, and add the $ sign before it.
Through dollar($) sign, you access the dbsignal class objects signal value attribute.

Are WebSocket messages cached on iOS?

Strange but I cannot find any information on that: if I write a [large] message to the WebSocket stream on iOS and the execution gets back to my code, is the message already sent or somehow buffered?
I'm using Starscream library but it just uses CFStream-s.
Looking at the source code for the Starscream library mentioned, the library appends the send operation to a NSOperation queue:
private func dequeueWrite(..) {
...
writeQueue.addOperation(operation)
}
and then immediately returns.
So when the one of the send methods returns, for example:
open func write(data: Data, completion: (() -> ())? = nil)
The message will not yet have been sent.
But as you can see you can pass a completion block to this method, that will be called when the whole message has been written to the underlying output stream. Note that this doesn't tell you anything about whether the message has actually been sent on the network, or if the sender has received it successfully.
To know if the sender has received and processed the message successfully, you need to wait for a response message - that is something you need to define in your application protocol.
Before using the Starscream library in production, you might want to report/fix some issues in it. While reviewing the send mechanism I noticed that if the OutputStream buffer is full on WebSocket.swift line 1254 the library tries sending the rest of the buffer in a busy loop rather than waiting for a hasSpaceAvailable event. This may waste a lot of CPU cycle if you send a large message.
Also, it looks like the case when stream.write returns 0, indicating that the output buffer is full, is incorrectly handled as an error.
Probably it use
func CFWriteStreamWrite(_ stream: CFWriteStream!,
_ buffer: UnsafePointer<UInt8>!,
_ bufferLength: CFIndex) -> CFIndex
the write call return "The number of bytes successfully written, 0 if the stream has been filled to capacity (for fixed-length streams), or -1 if either the stream is not open or an error occurs."
So yes, they are buffered. But I think that is the only option, a write function need to have the buffer because every socket have a max buffer zsize

QNX MsgReceive Pulse

I have a problem because I don't know how _pulse receiving works. If I have my data struct
typedef struct _my_data {
msg_header_t hdr;
int data;
} my_data_t;
and I am receiving only my msg I cant tell if it is a pulse
my_data_t msg;
...
rcvid = MsgReceive(g_Attach->chid, &msg, sizeof(msg), NULL);
when rcvid = 0 BUT how a program knows that it need to send _pulse in a form of msg (struct that I defined) or else how does it work. In addition is _IO_CONNECT a pulse? If yes why doesn't it have rcvid==0? - according to http://www.qnx.com/developers/docs/6.3.2/neutrino/lib_ref/n/name_attach.html
1 - _IO_CONNECT is not used for pulse. Its used for connect system call to resource managers. Example system calls are open(), close(), etc.
2 - You need to know whether the server or client is waiting on pulse message or not. For pulse message the blocking function in the resource manager will be MsgReceivePulse() and the client will use MsgSendPulse().
MsgSend() is used for normal message and MsgSendPulse() is for sending pulse message.
Similarly MsgReceive() is used for receiving normal message and MsgReceivePulse() is used for receiving pulse messages. Please refer to the QNX documents for more detailed description.
Both variants have different parameters like the functions for pulse messages do not have any parameter for return data because pulses are non blocking small messages which do not block for any reply but functions for normal messages have parameters for receive data.
You need to create channel and connection, for example
chid=ChannelCreate(0);
int pid=getpid();
coid=ConnectAttach(0, pid, chid, 0, 0);
and attach channel to connection.............
Then if you have two threads...............from one thread you can to call MsgSend function, for example MsgSend(coid, &(message), sizeof(message), &rmsg, sizeof(rmsg)); and in the other thread rcvid=MsgReceive(chid, (void*)&message, sizeof(message),NULL);

Resources