How to read a array value from the opcua server by client - client

I have been trying to do a simple OPC UA client server application using the open62541 stack. I can access the value from the open62541 implemented server. But i need to know, how a array value from the server can be interpreted/retrieved by the open62541 client?
Ex:
This is how i do for single value-
UA_Client_readValueAttribute(client, UA_NODEID_STRING(1, "value"), &value);
if(status == UA_STATUSCODE_GOOD &&
UA_Variant_hasScalarType(&value, &UA_TYPES[UA_TYPES_INT32])) {
printf("value is: %i\n", *(UA_Int32*)value.data);
}

Here is an example how to read the namespace array.
It works in the same way as any other array value:
UA_ReadRequest request;
UA_ReadRequest_init(&request);
UA_ReadValueId id;
UA_ReadValueId_init(&id);
id.attributeId = UA_ATTRIBUTEID_VALUE;
id.nodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_NAMESPACEARRAY);
request.nodesToRead = &id;
request.nodesToReadSize = 1;
UA_ReadResponse response = UA_Client_Service_read(client, request);
UA_StatusCode retval = UA_STATUSCODE_GOOD;
if(response.responseHeader.serviceResult != UA_STATUSCODE_GOOD)
retval = response.responseHeader.serviceResult;
else if(response.resultsSize != 1 || !response.results[0].hasValue)
retval = UA_STATUSCODE_BADNODEATTRIBUTESINVALID;
else if(response.results[0].value.type != &UA_TYPES[UA_TYPES_STRING])
retval = UA_STATUSCODE_BADTYPEMISMATCH;
if(retval != UA_STATUSCODE_GOOD) {
UA_ReadResponse_deleteMembers(&response);
return retval;
}
retval = UA_STATUSCODE_BADNOTFOUND;
UA_String *ns = (UA_String *)response.results[0].value.data;
for(size_t i = 0; i < response.results[0].value.arrayLength; ++i){
printf("The NS is %*.s", (int)ns[i].length, ns[i].data);
}
UA_ReadResponse_deleteMembers(&response);
The important thing is that response.results[0].value.data holds the array, and response.results[0].value.arrayLength the length of the array itself.

Related

GetRawInputDeviceInfo indicates a buffer size of 1 character for RIDI_DEVICENAME

I'm getting ridiculous behavior from RIDI_DEVICENAME. According to the documentation,
Return value
Type: UINT
If successful, this function returns a non-negative number indicating the number of bytes copied to pData.
If pData is not large enough for the data, the function returns -1. If pData is NULL, the function returns a value of zero. In both of these cases, pcbSize is set to the minimum size required for the pData buffer.
Call GetLastError to identify any other errors.
Ignoring the obvious problem that -1 is not a representable value in the UINT return type, it seems that the function should tell me the required size of the buffer, and if I supply a buffer of this size, the function should either succeed or at least follow its own rules for failure.
However, I'm not seeing this at all. On Windows 10, the Unicode version of the function sets pcbSize to 1 when pData is null and leaves it alone otherwise, failing in all cases. The ANSI version of the function sets pcbSize to 2 when pData is null, and otherwise doubles whatever value was passed in, and still fails.
Headers used for either version of test code:
#define WIN32_EXTRA_LEAN 1
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#include <windows.h>
ANSI test code:
std::string GetRawInputDeviceName( HANDLE hRaw )
{
UINT numChars = 0u;
INT validChars;
validChars = static_cast<INT>(::GetRawInputDeviceInfoA(hRaw, RIDI_DEVICENAME, nullptr, &numChars));
auto lasterror = ::GetLastError();
if (lasterror != ERROR_INSUFFICIENT_BUFFER) {
std::wcerr << L"Failed to get length of name of raw input device, retcode = " << validChars << L", last error = " << lasterror << L"\n";
return {};
}
std::string name;
name.resize(numChars);
validChars = static_cast<INT>(::GetRawInputDeviceInfoA(hRaw, RIDI_DEVICENAME, &name[0], &numChars));
lasterror = ::GetLastError();
if (validChars > 0) {
name.resize(validChars);
return name;
}
else {
std::wcerr << L"Failed to get name of raw input device, retcode = " << validChars << L", last error = " << lasterror << L"\n";
return {};
}
}
Unicode test code:
std::wstring GetRawInputDeviceName( HANDLE hRaw )
{
UINT numChars = 0u;
INT validChars;
validChars = static_cast<INT>(::GetRawInputDeviceInfoW(hRaw, RIDI_DEVICENAME, nullptr, &numChars));
auto lasterror = ::GetLastError();
if (lasterror != ERROR_INSUFFICIENT_BUFFER) {
std::wcerr << L"Failed to get length of name of raw input device, retcode = " << validChars << L", last error = " << lasterror << L"\n";
return {};
}
std::wstring name;
name.resize(numChars);
validChars = static_cast<INT>(::GetRawInputDeviceInfoW(hRaw, RIDI_DEVICENAME, &name[0], &numChars));
lasterror = ::GetLastError();
if (validChars > 0) {
name.resize(validChars);
return name;
}
else {
std::wcerr << L"Failed to get name of raw input device, retcode = " << validChars << L", last error = " << lasterror << L"\n";
return {};
}
}
On Windows 10 through RDP I'm getting ERROR_INSUFFICIENT_BUFFER consistently.
On Windows 8.1 running as a local user, I get ERROR_INSUFFICIENT_BUFFER if pData is null, and when I provide a buffer I get back failure ((UINT)-1) and GetLastError() returns zero.
I've also just tried proposing a likely-large-enough buffer size, and got failures as well.
What is going on, what is the right way to get the interface path name, and do I need administrative rights or to call some other APIs first? I don't seem to be having any problems calling GetRawInputDeviceList or using RIDI_DEVICEINFO mode of GetRawInputDeviceInfo... but I need the interface path in order to go further.
Windows HID Device Name Format
https://stackoverflow.com/a/64320052/103167
the GetRawInputDeviceName have several errors in declaration / implementation / documentation
by fact more correct declare return value as signed ( LONG or INT) but not UINT
exist 3 case:
1. function return negative value (or if want -1) : this is error
case, and by design - last error must be set. but really it not
always set (implementation error).
most common errors:
pcbSize or pData point to invalid or read only memory location. usual error in this case ERROR_NOACCESS (translated from
STATUS_ACCESS_VIOLATION)
hDevice not valid handle - ERROR_INVALID_HANDLE is returned
uiCommand not valid RIDI_XXX constant - ERROR_INVALID_PARAMETER
*pcbSize is not large enough for the data - in this case *pcbSize is set to the minimum size required for the pData buffer. ERROR_INSUFFICIENT_BUFFER
again - only in this case (-1) exist sense call GetLastError();
2. function return 0 this possible only in case when pData is NULL.
*pcbSize is set to the minimum size required for the pData buffer.
3. function return positive value ( > 0) this mean that this count of
bytes (in case RIDI_PREPARSEDDATA or RIDI_DEVICEINFO ) or
characters (in case RIDI_DEVICENAME) written to buffer
so documentation is wrong here:
pcbSize
[in, out]
Pointer to a variable that contains the size, in bytes, of the data in
pData.
in case RIDI_DEVICENAME in characters
so already visible very serious problems with design (type of return value - unsigned) and mixed bytes/characters. many different cases.
but then exist critical error in implementation. in begin of function handle hDevice converted to pointer.
PDEVICEINFO pDeviceInfo = HMValidateHandle(hDevice, TYPE_DEVICEINFO);
(if 0 returned - we got -1 on exit with ERROR_INVALID_HANDLE).
in DEVICEINFO exist UNICODE_STRING ustrName - this name and copied to user mode
switch (uiCommand) {
case RIDI_DEVICENAME:
/*
* N.b. UNICODE_STRING counts the length by the BYTE count, not by the character count.
* Our APIs always treat the strings by the character count. Thus, for RIDI_DEVICNAME
* only, cbOutSize holds the character count, not the byte count, in spite of its
* name. Confusing, but cch is the way to be consistent.
*/
cbOutSize = pDeviceInfo->ustrName.Length / sizeof(WCHAR) + 1; // for Null terminator
break;
//...
}
required cbOutSize compared with cbBufferSize = *pcbSize;
and if (cbBufferSize >= cbOutSize) api begin copy operation
exist next code
case RIDI_DEVICENAME:
if (cbOutSize <= 2) { // !!!! error !!!!
retval = -1;
goto leave;
}
RtlCopyMemory(pData, pDeviceInfo->ustrName.Buffer, pDeviceInfo->ustrName.Length);
((WCHAR*)pData)[1] = '\\'; // convert nt prefix ( \??\ ) to win32 ( \\?\ )
((WCHAR*)pData)[cbOutSize - 1] = 0; // make it null terminated
break;
cbOutSize here - is (len + 1) of device name (which we not control). so if name is zero length - always -1 is returned (error #1) but last error not set ( error #2 )
of course exist and error #3 - why is device name is 0 length ? this must not be. but in case terminal service devices - (virtual mouse/ keyboard device created on UMB bus ) - exist this result.
full code for api ( in kernel)
UINT NtUserGetRawInputDeviceInfo(
HANDLE hDevice,
UINT uiCommand,
LPVOID pData,
PUINT pcbSize)
{
UINT cbOutSize = 0;
UINT cbBufferSize;
int retval = 0;
EnterCrit(0, UserMode);
UserAtomicCheck uac;
try {
ProbeForRead(pcbSize, sizeof(UINT), sizeof(DWORD));
cbBufferSize = *pcbSize;
} except (EXCEPTION_EXECUTE_HANDLER) {
UserSetLastError(RtlNtStatusToDosError(GetExceptionCode()));// ERROR_NOACCESS
retval = -1;
goto leave1;
}
EnterDeviceInfoListCrit_();
PDEVICEINFO pDeviceInfo = HMValidateHandle(hDevice, TYPE_DEVICEINFO);
if (pDeviceInfo == NULL) {
UserSetLastError(ERROR_INVALID_HANDLE);
retval = -1;
goto leave;
}
/*
* Compute the size of the output and evaluate the uiCommand.
*/
switch (uiCommand) {
case RIDI_PREPARSEDDATA:
if (pDeviceInfo->type == DEVICE_TYPE_HID) {
cbOutSize = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.DescriptorSize;
} else {
cbOutSize = 0;
}
break;
case RIDI_DEVICENAME:
/*
* N.b. UNICODE_STRING counts the length by the BYTE count, not by the character count.
* Our APIs always treat the strings by the character count. Thus, for RIDI_DEVICNAME
* only, cbOutSize holds the character count, not the byte count, in spite of its
* name. Confusing, but cch is the way to be consistent.
*/
cbOutSize = pDeviceInfo->ustrName.Length / sizeof(WCHAR) + 1; // for Null terminator
break;
case RIDI_DEVICEINFO:
cbOutSize = sizeof(RID_DEVICE_INFO);
break;
default:
UserSetLastError(ERROR_INVALID_PARAMETER);
retval = -1;
goto leave;
}
if (pData == NULL) {
/*
* The app wants to get the required size.
*/
try {
ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
*pcbSize = cbOutSize;
} except (EXCEPTION_EXECUTE_HANDLER) {
UserSetLastError(RtlNtStatusToDosError(GetExceptionCode()));// ERROR_NOACCESS
retval = -1;
goto leave;
}
retval = 0;
} else {
if (cbBufferSize >= cbOutSize) {
try {
ProbeForWrite(pData, cbBufferSize, sizeof(DWORD));
switch (uiCommand) {
case RIDI_PREPARSEDDATA:
if (pDeviceInfo->type == DEVICE_TYPE_HID) {
RtlCopyMemory(pData, pDeviceInfo->hid.pHidDesc->pPreparsedData, cbOutSize);
}
break;
case RIDI_DEVICENAME:
if (cbOutSize <= 2) { // !!!!
retval = -1;
goto leave;
}
RtlCopyMemory(pData, pDeviceInfo->ustrName.Buffer, pDeviceInfo->ustrName.Length);
((WCHAR*)pData)[1] = '\\'; // make it null terminated
((WCHAR*)pData)[cbOutSize - 1] = 0; // make it null terminated
break;
case RIDI_DEVICEINFO:
{
PRID_DEVICE_INFO prdi = (PRID_DEVICE_INFO)pData;
ProbeForRead(prdi, sizeof(UINT), sizeof(DWORD));
if (prdi->cbSize != cbOutSize) {
MSGERRORCLEANUP(ERROR_INVALID_PARAMETER);
}
ProbeForWrite(prdi, sizeof(RID_DEVICE_INFO), sizeof(DWORD));
RtlZeroMemory(prdi, sizeof(RID_DEVICE_INFO));
prdi->cbSize = cbOutSize;
switch (pDeviceInfo->type) {
case DEVICE_TYPE_HID:
prdi->dwType = RIM_TYPEHID;
prdi->hid.dwVendorId = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.VendorID;
prdi->hid.dwProductId = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.ProductID;
prdi->hid.dwVersionNumber = pDeviceInfo->hid.pHidDesc->hidCollectionInfo.VersionNumber;
prdi->hid.usUsagePage = pDeviceInfo->hid.pHidDesc->hidpCaps.UsagePage;
prdi->hid.usUsage = pDeviceInfo->hid.pHidDesc->hidpCaps.Usage;
break;
case DEVICE_TYPE_MOUSE:
prdi->dwType = RIM_TYPEMOUSE;
prdi->mouse.dwId = pDeviceInfo->mouse.Attr.MouseIdentifier;
prdi->mouse.dwNumberOfButtons = pDeviceInfo->mouse.Attr.NumberOfButtons;
prdi->mouse.dwSampleRate = pDeviceInfo->mouse.Attr.SampleRate;
break;
case DEVICE_TYPE_KEYBOARD:
prdi->dwType = RIM_TYPEKEYBOARD;
prdi->keyboard.dwType = GET_KEYBOARD_DEVINFO_TYPE(pDeviceInfo);
prdi->keyboard.dwSubType = GET_KEYBOARD_DEVINFO_SUBTYPE(pDeviceInfo);
prdi->keyboard.dwKeyboardMode = pDeviceInfo->keyboard.Attr.KeyboardMode;
prdi->keyboard.dwNumberOfFunctionKeys = pDeviceInfo->keyboard.Attr.NumberOfFunctionKeys;
prdi->keyboard.dwNumberOfIndicators = pDeviceInfo->keyboard.Attr.NumberOfIndicators;
prdi->keyboard.dwNumberOfKeysTotal = pDeviceInfo->keyboard.Attr.NumberOfKeysTotal;
break;
}
}
break;
default:
__assume(false);
}
} except (EXCEPTION_EXECUTE_HANDLER) {
UserSetLastError(RtlNtStatusToDosError(GetExceptionCode()));// ERROR_NOACCESS
retval = -1;
goto leave;
}
retval = cbOutSize;
} else {
/*
* The buffer size is too small.
* Returns error, storing the required size in *pcbSize.
*/
retval = -1;
try {
ProbeForWrite(pcbSize, sizeof(UINT), sizeof(DWORD));
*pcbSize = cbOutSize;
UserSetLastError(ERROR_INSUFFICIENT_BUFFER);
} except (EXCEPTION_EXECUTE_HANDLER) {
UserSetLastError(RtlNtStatusToDosError(GetExceptionCode()));// ERROR_NOACCESS
retval = -1;
goto leave;
}
}
}
leave:
LeaveDeviceInfoListCrit_();
leave1:
UserSessionSwitchLeaveCrit();
return retval;
}
then GetRawInputDeviceInfoA add additional errors compare GetRawInputDeviceInfoW - the value from *pcbSize by some reason multiple on 2. but again - this error in all case.
note that DeviceName (formatted from strings returned from driver on IRP_MN_QUERY_ID have very strict restrictions:
If a driver returns an ID with an illegal character, the system will
bug check. Characters with the following values are illegal in an ID
for this IRP:
Less than or equal to 0x20 (' ')
Greater than 0x7F
Equal to 0x2C (',')
so even after covert unicode to ansi - length of device name will be the same ( all symbols < 0x80 ). so not need *2 buffer size for Ansi version.
then i already view error in your code - you call ::GetLastError(); unconditionally after GetRawInputDeviceInfoW - but returned value have sense only in case api return -1
explain for observed behavior:
for local devices api in general work correct (if no mistakes in our code)
for terminal service devices - was 0 length ustrName. as result if we pass NULL in pData - return value will be
pDeviceInfo->ustrName.Length / sizeof(WCHAR) + 1;
because pDeviceInfo->ustrName.Length == 0 - 1 will be returned inside *pcbSize
in case A version - -by mistake - 2*1==2 will be returned.
but when e pass not NULL in pData - we trap in this
if (cbOutSize <= 2) { // !!!! error !!!!
retval = -1;
goto leave;
}
so you can pass any by size buffer, anyway, because (cbOutSize <= 2) - -1 will be returned and last error not set
possible solution - at first - never use ansi version - GetRawInputDeviceInfoA
use this wrapper function.
ULONG GetRawInputDeviceInfoExW(_In_opt_ HANDLE hDevice,
_In_ UINT uiCommand,
_Inout_updates_bytes_to_opt_(*pcbSize, *pcbSize) LPVOID pData,
_Inout_ PUINT pcbSize)
{
switch (int i = GetRawInputDeviceInfoW(hDevice, uiCommand, pData, pcbSize))
{
case 0:
return ERROR_INSUFFICIENT_BUFFER;
case 1:
return ERROR_INVALID_NAME;
default:
if (0 > i)
{
return GetLastError();
}
*pcbSize = i;
return NOERROR;
}
}
example of usage: (/RTCs must be disabled )
void Demo()
{
PRAWINPUTDEVICELIST pRawInputDeviceList = 0;
UINT uiNumDevices = 0;
UINT cch, cchAllocated = 0;
union {
PVOID buf;
PWSTR name;
};
buf = 0;
while (0 <= (int)GetRawInputDeviceList(pRawInputDeviceList, &uiNumDevices, sizeof(RAWINPUTDEVICELIST)))
{
if (pRawInputDeviceList)
{
do
{
HANDLE hDevice = pRawInputDeviceList->hDevice;
ULONG dwError;
while (ERROR_INSUFFICIENT_BUFFER == (dwError =
GetRawInputDeviceInfoExW(hDevice, RIDI_DEVICENAME, name, &(cch = cchAllocated))))
{
if (cch > cchAllocated)
{
cchAllocated = RtlPointerToOffset(buf = alloca((cch - cchAllocated) * sizeof(WCHAR)),
pRawInputDeviceList) / sizeof(WCHAR);
}
else
{
__debugbreak();
}
}
if (dwError == NOERROR)
{
DbgPrint("[%p, %x %S]\n", hDevice, pRawInputDeviceList->dwType, name);
}
else
{
DbgPrint("error = %u\n", dwError);
}
} while (pRawInputDeviceList++, --uiNumDevices);
break;
}
pRawInputDeviceList = (PRAWINPUTDEVICELIST)alloca(uiNumDevices * sizeof(RAWINPUTDEVICELIST));
}
}
This code is working fine on my PC. Not sure, but it indeed could be RDP issue.
UINT result = ::GetRawInputDeviceInfoW(m_Handle, RIDI_DEVICENAME, nullptr, &size);
if (result == static_cast<UINT>(-1))
{
//PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
return false;
}
DCHECK_EQ(0u, result);
std::wstring buffer(size, 0);
result = ::GetRawInputDeviceInfoW(m_Handle, RIDI_DEVICENAME, buffer.data(), &size);
if (result == static_cast<UINT>(-1))
{
//PLOG(ERROR) << "GetRawInputDeviceInfo() failed";
return false;
}
DCHECK_EQ(size, result);

Filtering return on serial port

I have a CO2 sensor on my Arduino Mega and sometimes randomly when I'm reading the CO2 measurement, the sensor will return a "?". The question mark causes my program to crash and return "input string was not in a correct format".
I haven't tried anything because I don't know what approach would be the best for this. The CO2 sensor returns the measurement in the form of "Z 00000" but when this question mark appears it shows that all that returned was a "\n". Currently, I have the program just reading the 5 digits after the Z.
if (returnString != "")
{
val = Convert.ToDouble(returnString.Substring(returnString.LastIndexOf('Z')+ 1));
}
What I expect to return is the digits after Z which works but every so often I will get a random line return which crashes everything.
According to the C# documentation the ToDouble method throws FormatException whenever the input string is invalid. You should catch the exception to avoid further issues.
try {
val = Convert.ToDouble(returnString.Substring(returnString.LastIndexOf('Z')+ 1));
}
catch(FormatException e) {
//If you want to do anything in case of an error
//Otherwise you can leave it blank
}
Also I'd recommend using some sort of statemachine for parsing the data in your case, that could discard all invalid characters. Something like this:
bool z_received = false;
int digits = 0;
int value = 0;
//Called whenever you receive a byte from the serial port
void onCharacter(char input) {
if(input == 'Z') {
z_received = true;
}
else if(z_received && input <= '9' && input >= '0') {
value *= 10;
value += (input - '0');
digits++;
if(digits == 5) {
onData(value);
value = 0;
z_received = false;
digits = 0;
}
}
else {
value = 0;
z_received = false;
digits = 0;
}
}
void onData(int data) {
//do something with the data
}
This is just a mock-up, should work in your case if you can direct the COM port's byte stream into the onCharacter function.

Omnet++, A cRuntimeError exception is about to be thrown

I'm currently using Omnet++, and veins, and I have this runtime error appearing suddenly, and I am not able to understand it in order to fix it properly.
Error in module (TraCIDemoRSU11p) RSUExampleScenario.rsu[0].appl
(id=8) at event #6180, t=53.956510612297: Array of size 220 indexed by
220.
TRAPPING on the exception above, due to a debug-on-errors=true configuration option. Is your debugger ready?
I am assuming that it might be related to this message I am sending from the RSU to the vehicles with this code, but I am not sure how it's related.
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message DelayedFromControllerMessage extends WaveShortMessage {
string vehiclesList [220] ;
}
I am using omnet++ Version: 5.0 and Veins 4.4
Edited, I'm using the array in these places:
1-
void TraCIDemoRSU11p::sendDelayedMessage(std::list<const char *> vehicleList) {
sentDelayedMessage = true;
//vehicleList = {};
t_channel channel = dataOnSch ? type_SCH : type_CCH;
DelayedFromControllerMessage* dsm = prepareDelayedSM("delayed",dataLengthBits, channel, dataPriority, -1,2,vehicleList);
std::list<const char *>::iterator it = vehicleList.begin();
//const char * v;
char* vx = new char [100];
vx[0] = '\0';
for(int i=0; i<vehicleList.size(); i++){
//v =*it;
strcpy(vx,*it);
//vx = *it;
++it;
dsm->setVehiclesList(i, vx);
}
if (sendDelayedEvt->isScheduled()) {
cancelAndDelete(sendDelayedEvt);
}else {
delete sendDelayedEvt;
}
sendDelayedEvt = new cMessage("delayed evt", SEND_DELAYED_EVT); // create event object to use it in timing
simtime_t offSet = dblrand() * (par("beaconInterval").doubleValue());
TimeStart = simTime() + offSet;
scheduleAt(TimeStart, sendDelayedEvt);
sendDelayedSM(dsm);
}
2-
DelayedFromControllerMessage* BaseWaveApplLayer:: prepareDelayedSM(const char * name, int lengthBits, t_channel channel, int priority, int rcvId,int serial,std::list<const char *>vehicleList ) {
DelayedFromControllerMessage* dsm = new DelayedFromControllerMessage(name);
dsm->addBitLength(headerLength);
dsm->addBitLength(lengthBits);
switch (channel) {
case type_SCH: dsm->setChannelNumber(Channels::SCH1); break; //will be rewritten at Mac1609_4 to actual Service Channel. This is just so no controlInfo is needed
case type_CCH: dsm->setChannelNumber(Channels::CCH); break;
}
dsm->setPsid(0);
dsm->setPriority(priority);
dsm->setWsmVersion(1);
dsm->setTimestamp(simTime());
dsm->setSenderAddress(myId);
dsm->setRecipientAddress(rcvId);
dsm->setSenderPos(curPosition);
dsm->setSerial(serial);
std::list<const char *>::iterator it = vehicleList.begin();
const char * v;
for(int i=0; i<vehicleList.size(); i++){
v =*it;
++it;
VLvar1.push_back(v);
dsm->setVehiclesList(i, v);
}
if ((std::string)name == "beacon") {
DBG << "Creating Beacon with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
if ((std::string)name == "delayed") {
DBG << "Creating Data with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
return dsm;
}
3-
void MyTraCIDemo11p::onDataDelayed(DelayedFromControllerMessage* dsm) {
int x = 0;
std::string vehichleId = mobility->getExternalId();
for (int i=0 ; i < dsm->getVehiclesListArraySize();i++)
{
vehicleList.push_back(std::string(dsm->getVehiclesList(i)));
}
ttry = std::find(vehicleList.begin(), vehicleList.end(), vehichleId);
if (vehichleId == *ttry){
x = 1;
}
if (state == QUEUING && x == 1){
findHost()->bubble("Received ");
state = WAITING;
stateToString(state);
}
}
The message should be sent from the RSU to the vehicles.
Even without seeing the actual code from the application (appl) or from the configuration file you are using, I am guessing you are trying to get the last element (element 220) from the array.
The error message already tells what the problem is. Your array has a size of 220 and you are trying to use the index 220 which is not possible, since array indexes start at 0. Therefore for addressing the last element in your array, you have to use index 221.
I am not sure if this is the reason for your error:
ttry = std::find(vehicleList.begin(), vehicleList.end(), vehichleId);
if (vehichleId == *ttry){
x = 1;
}
But, It is better to write it this way:
if (std::find(vehicleList.begin(), vehicleList.end(), vehichleId) != vehicleList.end()){
x = 1;
}
I don't recommend referencing thefind iterator (i.e., *ttry) if it is not found, it is like referencing *(vehicleList.end()).
it seems to me you have two veichleList variables, an array in the dsm and another one which is a vector. is this correct? if yes, you should make sure that the veichleList.size() is always less or equal 220.
Check this tutorial to learn how to debug your project in omnet++:
https://docs.omnetpp.org/tutorials/tictoc/part2/
So i ended up finding a solution for this issue just now.
it was by doing this:
cplusplus {{
#include "veins/modules/messages/WaveShortMessage_m.h"
}}
class WaveShortMessage;
message DelayedFromControllerMessage extends WaveShortMessage {
string vehiclesList [] ;
}
=====
DelayedFromControllerMessage* BaseWaveApplLayer:: prepareDelayedSM(const char * name, int lengthBits, t_channel channel, int priority, int rcvId,int serial,std::list<const char *>vehicleList ) {
DelayedFromControllerMessage* dsm = new DelayedFromControllerMessage(name);
dsm->addBitLength(headerLength);
dsm->addBitLength(lengthBits);
switch (channel) {
case type_SCH: dsm->setChannelNumber(Channels::SCH1); break; //will be rewritten at Mac1609_4 to actual Service Channel. This is just so no controlInfo is needed
case type_CCH: dsm->setChannelNumber(Channels::CCH); break;
}
dsm->setPsid(0);
dsm->setPriority(priority);
dsm->setWsmVersion(1);
dsm->setTimestamp(simTime());
dsm->setSenderAddress(myId);
dsm->setRecipientAddress(rcvId);
dsm->setSenderPos(curPosition);
dsm->setSerial(serial);
int NS = 0;
std::list<const char *>::iterator itPD = vehicleList.begin();
const char * vPD;
int i0 = 0;
while(itPD != vehicleList.end()){
vPD = *itPD;
++itPD;
++NS;
dsm->setVehiclesListArraySize(NS);
dsm->setVehiclesList(i0, vPD);
++i0;
VLvar1.push_back(vPD);
}
if ((std::string)name == "beacon") {
DBG << "Creating Beacon with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
if ((std::string)name == "delayed") {
DBG << "Creating Data with Priority " << priority << " at Applayer at " << dsm->getTimestamp() << std::endl;
}
return dsm;
}
I removed the array size and placed with a manual counter in BaseWaveApplLayer:: prepareDelayedSM using a while loop. I thought about posting the solution to help others when facing a similar problem. :)

why does linux 0.11 use read lock when doing block reading?

I have read linux source code about block device part of version 0.11 and i found if two processes do reading block operation, one will lock the buffer(bh),another one has to wait this lock, my question is why reading will block each other by using such kind of locker? isn't it supposed to be write operation?
make_request (int major, int rw, struct buffer_head *bh)
{
struct request *req;
int rw_ahead;
if (rw_ahead = (rw == READA || rw == WRITEA))
{
if (bh->b_lock)
return;
if (rw == READA)
rw = READ;
else
rw = WRITE;
}
if (rw != READ && rw != WRITE)
panic ("Bad block dev command, must be R/W/RA/WA");
lock_buffer (bh);
if ((rw == WRITE && !bh->b_dirt) || (rw == READ && bh->b_uptodate))
{
unlock_buffer (bh);
return;
}
repeat:
if (rw == READ)
req = request + NR_REQUEST;
else
req = request + ((NR_REQUEST * 2) / 3);
/* find an empty request */
while (--req >= request)
if (req->dev < 0)
break;
if (req < request)
{
if (rw_ahead)
{
unlock_buffer (bh);
return;
}
sleep_on (&wait_for_request);
goto repeat;
}
req->dev = bh->b_dev;
req->cmd = rw;
req->errors = 0;
req->sector = bh->b_blocknr << 1;
req->nr_sectors = 2;
req->buffer = bh->b_data;
req->waiting = NULL;
req->bh = bh;
req->next = NULL;
add_request (major + blk_dev, req);
}

libusb data transfer

Hii I have to make a code to read data from usb drive which can be pendrive and later a data acquisition card . i have written this much of code which detects all usb connection n print their info. Altough i don't know how to proceed further . I m also confused as to reading data from say pendrive means as in opening some files or what? Please also tell how to find endpoint of device currently i'm jsut using hit n trial to find it .
PLEASE help me out .I have read whole documentation on synchronous and asynchronous I/O.
enter code here
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
//=========================================================================
// This program detects usb and print out their details
//=========================================================================
int main (int argc, char *argv)
{
libusb_device **devList = NULL;
libusb_device *devPtr = NULL;
libusb_device_handle *devHandle = NULL;
libusb_context *ctx = NULL; //a libusb session
struct libusb_device_descriptor devDesc;
unsigned char strDesc[256];
ssize_t numUsbDevs = 0; // pre-initialized scalars
ssize_t idx = 0;
int retVal = 0;
//========================================================================
// test out the libusb functions
//========================================================================
printf ("*************************\n USB Detection Program:\n*************************\n");
retVal = libusb_init (&ctx);
if(retVal < 0) {
printf ("%d",retVal," Init Error "); //there was an error
return 1;
}
//========================================================================
// Get the list of USB devices visible to the system.
//========================================================================
numUsbDevs = libusb_get_device_list (ctx, &devList);
//========================================================================
// Loop through the list, looking for the device
//========================================================================
while (idx < numUsbDevs)
{
printf ("\n\n[%d]\n", idx+1);
//=====================================================================
// Get next device pointer out of the list, use it to open the device.
//=====================================================================
devPtr = devList[idx];
retVal = libusb_open (devPtr, &devHandle);
if (retVal != LIBUSB_SUCCESS)
break;
//=====================================================================
// Get the device descriptor for this device.
//=====================================================================
retVal = libusb_get_device_descriptor (devPtr, &devDesc);
if (retVal != LIBUSB_SUCCESS)
break;
//=====================================================================
// Get the string associated with iManufacturer index.
//=====================================================================
printf ("iManufacturer = %d", devDesc.iManufacturer);
if (devDesc.iManufacturer > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iManufacturer, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//========================================================================
// Get string associated with iProduct index.
//========================================================================
printf (" \niProduct = %d", devDesc.iProduct);
if (devDesc.iProduct > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iProduct, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//==================================================================
// Get string associated with iSerialNumber index.
//==================================================================
printf (" \niSerialNumber = %d", devDesc.iSerialNumber);
if (devDesc.iSerialNumber > 0)
{
retVal = libusb_get_string_descriptor_ascii
(devHandle, devDesc.iSerialNumber, strDesc, 256);
if (retVal < 0)
break;
printf (" string = %s", strDesc);
}
//==================================================================
// Print product id and Vendor id
//==================================================================
printf (" \nProductid = %d", devDesc.idProduct);
printf (" \nVendorid = %d", devDesc.idVendor);
//========================================================================
// Close and try next one.
//========================================================================
libusb_close (devHandle);
devHandle = NULL;
idx++;
//========================================================================
// Selection of device by user
//========================================================================
if(idx==numUsbDevs)
{ printf("\n\nselect the device : ");
scanf("%d",&idx);
if(idx > numUsbDevs)
{printf("Invalid input, Quitting.............");
break; }
devPtr = devList[idx-1];
retVal = libusb_open (devPtr, &devHandle);
if (retVal != LIBUSB_SUCCESS)
break;
retVal = libusb_get_device_descriptor (devPtr, &devDesc);
if (retVal != LIBUSB_SUCCESS)
break;
printf (" \nProductid = %d", devDesc.idProduct);
printf (" \nVendorid = %d", devDesc.idVendor);
unsigned char data[4] ; //data to read
//data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values
int r; //for return values
r = libusb_claim_interface(devHandle, 1); //claim interface 0 (the first) of device
if(r < 0) {
printf("\nCannot Claim Interface");
return 1;
}
printf("\nClaimed Interface");
int actual_length; //used to find out how many bytes were written
r = libusb_bulk_transfer(devHandle,LIBUSB_ENDPOINT_IN, data, 2, &actual_length, 0);
if (r == 0 && actual_length == sizeof(data)) {
// results of the transaction can now be found in the data buffer
// parse them here and report button press
}
else {
error();
}
r = libusb_release_interface(devHandle, 1); //release the claimed interface
if(r!=0) {
printf("\nCannot Release Interface");
return 1;
}
printf("\nReleased Interface");
idx=numUsbDevs +2;
}
} // end of while loop
if (devHandle != NULL)
{
//========================================================================
// Close device if left open due to break out of loop on error.
//========================================================================
libusb_close (devHandle);
}
libusb_exit (ctx); //close the session
printf ("\n*************************\n Done\n*************************\n");
return 0;
}
//==========================================
// EOF
//====================

Resources