Asynchronous Values Update using GCDAsynSocket api - ios

I am developing one application in which I need to update multiple values like Engine RPM,Speed etc. parameters at a time using OBD connector. I need to achieve asynchronous command/response . For this I am sending commands using [gcdAsyncSocket writeData:data withTimeout:-1 tag:uniqueTag]; asynchronously with unique tag.
But when gcdAsync's delegate method "socketDidReadDatawithTag" is called, it returns the data but it is not proper.e.g. If I have sent one command "010C\r" (Read RPM), and "010D\r" (Speed),with Tag 263 and 264 respectively ,and if I parse the response with tag 264 in socketDidReadDatawithTag , sometimes it returns me the data of RPM. (My response gets Mixed up or OBD Device is unable to handle asynchronous response)
NSLog(#"Command Sent for Async : %#",commandString);
NSData *data = [commandString dataUsingEncoding:NSASCIIStringEncoding];
long obdObjectTag = [obdObject getPIDTag];//Unique Tag
[gcdAsyncSocket writeData:data withTimeout:-1 tag:obdObjectTag];
NSData *readData = [#">" dataUsingEncoding:NSASCIIStringEncoding];
[gcdAsyncSocket readDataToData:readData withTimeout:-1 tag:obdObjectTag];
And in socketdidReadDatawithTag data and tag are mismatched.

The OBD-II connector (I assume it's an ELM-327) cannot really handle asynchronous calls as far as I know.
It cannot handle multiple requests at once. You send 1 command, and the OBD-II device will gather that info from the OBD-bus and return with an answer. Then it will process your next command. Ofcourse, the commands you send end up in a buffer, that will be processed one by one.
I'm thinking this might be a problem for you to make it, but I'm not sure.
I'm not familiar at all with the ios programming and what happens with those tags. You set those tags to identify what paramters are the data for?
In the reply data, you can also see for what parameter it is meant, so in the answer itself you can see that data represents RPM or Speed etc.
I hope the OBD-II part has shed some light on it. Will check this question more for some discussion perhaps.

Related

Clarification on CoAp implementation for contikiOS

I'm trying to send packets over CoAP between two TI 2650 sensortags. I used the logic from the "er-rest-example" provided by contiki 3.0, that is:
coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
coap_set_header_uri_path(request, url);
coap_set_payload(request, (uint8_t*)msg, sizeof(msg) - 1);
COAP_BLOCKING_REQUEST(&server_ip, REMOTE_PORT, request, client_chunk_handler);
When I started the program, it works as expected until the first time COAP_BLOCKING_REQUEST is called, at which point the program seems to freeze (doesn't react to button presses anymore).
So I assume COAP_BLOCKING_REQUEST blocks until it receives a response, which is not suitable for my project. Can anyone confirm that?
UPDATE:
Going forward from that assumption, my question now is, what steps to I have to take to send out a packet?
Do I use the coap_send_message function from er-coap.c or the coap_send_transaction function from er-coap-transaction.c?
I want to figure out what functions I have to call in which order to configure the packet correctly and then send it out with the correct function (which I guess would be one of the above).
Maybe there is some documentation out there that I haven't found yet and someone could point me to it?
Cheers

Messagebox working in debug mode but not in normal run

I am making a software for GSM Modem. It works on serial communication using AT commands. We give AT commands to it and it respond via serial communication. I am giving it a command to check balance in a SIM AT+CUSD=1,"*141#". Its response is like this:
+CUSD: 0, "Your balance is ... xxxxxxx "
Now I want to display this on a messagebox. This is the small code I am using:
String data = serialPort1.ReadExisting(); //to receive serial data and store it in data strig
logsTextBox.AppendText(data); // display it in text box
logsTextBox.AppendText("\n");
if (data.Contains("+CUSD:"))
{
MessageBox.Show(data);
}
Now when I put breakpoint and debug the code, it works properly and show complete data in message box but when I run it normally it shows just few characters in message box. Like this:
Instead it should be like this:
The problem what I have found is when debug all the data content which is shown in 2nd image gets save in data variable so it is displayed completely in message box. But when in normal run, the complete data is not received in string data so thats why it shows less data as shown in first image. How to solve this issue. What could be the reason. Please help.
This is a typical behavior for a serial port. They are very slower. When the DataReceived event fires, you'd typically only get one or two characters. Notably is that it works well when you debug because single-stepping through the code gives the lots of time to serial port to receive additional characters. But it will go Kaboom as soon as you run without a debugger because the string isn't long enough.
You'll need to modify the code by appending the string you receive to a string variable at class scope. Only parse the string after you've received all the characters you expected. You'll need some way to know that you've received the full response. Most typically serial devices will terminate the string with a special character. Often a line-feed.
If that's the case then you can make it easy by setting the SerialPort.NewLine property to that terminator and calling ReadLine() instead of ReadExisting().
You should call ReadExisting until empty string is returned, concatenating the results to data on each call. Perhaps debug mode has a larger read buffer for the serial port than normal mode.

Smart way to not kill WebService

It's my code :
for (FlightScopePlayerPlayer *player in self.selectedPlayers) {
BaseballPlayer_GetBaseballProfileRequest *re = [[BaseballPlayer_GetBaseballProfileRequest alloc]initWithPlayerID:player.ID];
[bseModel.myFlightScopeClient.baseballPlayerServiceClient GetBaseballProfile:re
onCompleted:^(id response) {
BaseballPlayer_GetBaseballProfileResponse *res = (BaseballPlayer_GetBaseballProfileResponse *)response;
self.player = res.player;
[self.baseballPlayerList addObject:self.player];
[DelegateHelper performProtocol:#protocol(LoadPlayersFromWSModelCallbackDelegate)
withTarget:self.delegates
withSelector:#selector(isResponseRedyToUseAfterGetProfile:)
withArgument:self];
This construction can kill my webservice. What is the smarter way to send this? The idea is that in array are objects and i want to send request for everyone but if in the array will be 1000 objects Webservice can die so my idea is send request when the previous is finished and send delegate at the end.
Ideally you'd have a different webservice.
Assuming you can't change, you need to queue your requests so you don't make too many at any one time and you can suspend processing if required. Potentially you can also retry failed requests by adding them back on to the end of the queue.
NSOperationQueue is appropriate for this. You can use NSBlockOperation to contain your processing logic to call the webservice. Be sure to set maxConcurrentOperationCount to some value between 1 and 4.
You can use RQOperation
Basically the idea is to store the web API calls in an array and then you can execute them in serial manner. (Once the previous is complete, execute the next one)
It has nice sample within. Hope that helps.
Not enough reps to post as comment, hence answer.

RedPark Serial Cable partial data

I have an RFID scanner attached to a RedPark serial cable connected to an iPad app. When people scan their RFID cards, I get a callback with -readBytesAvailable:. However, sometimes it doesn't give me the entire RFID in one call. Sometimes it send it in two calls.
How can I determine if I've received everything? When my code takes the first callback's data and tries to use it, I get an error, because let's say the RFID was "123456789" sometimes I'll get one call with #"12" and a second call with #"3456789". So I try to process #"12" and get a user not found error, then I try to process #"3456789" and get a user not found error.
How can I tell if I'm done reading data? The lengths of the RFIDs can vary from vendor to vendor, so I can't just assume I need to read a certain number of digits.
This is the method I use to receive the data from the scanner through the RedPark:
- (void) readBytesAvailable:(UInt32)length {
NSLog(#"readBytesAvailable: %lu", length);
UInt8 rxLoopBuff[LOOPBACK_TEST_LEN];
[self.rfidManager read:rxLoopBuff Length:length];
NSString *rfid = [[NSString alloc] initWithBytes:rxLoopBuff length:length encoding:NSUTF8StringEncoding];
NSLog(#"rfid=%#", rfid);
[self receivedScanOfRFID:rfid];
}
Serial port gives you no control over packetization. Data is just a stream of bytes with no way to predict which bytes appear in each read call. You have to parse the data stream itself to interpret the contents and understand start/end of your messages. You either need to look for a reliable terminating character or potentially use a timeout approach where you do multiple reads until you get no more data for some period of time. I don't recommend the timeout approach.

Does App WAIT for -initWithContentsOfURL: to retrieve web-data?

I am trying retrieve data from a .php file on a server from within an iPhone OS app. In one method, I employ the following code:
NSString *aString = [[NSString alloc] initWithContentsOfURL:aURL encoding:anEncoding error:nil];
//See what I got
NSLog(aString);
When I run the App it seems like the App runs through the code so fast I doubt that there was enough time for a Data Request to have transpired. The resulting string is totally empty, which further supports my suspicions. What is happening here? Is the app not waiting for the -initWithContentsOfURL to retrieve data from the .php file on my server? If the app does not wait for this method, is there another method I can use to perform a Data Request in a manner that WAITS for the request to be completed before moving onto the next code?
(I've also read a little on NSURLConnection -- is this maybe what I should be looking into instead of -initWithContentsOfURL?)
NSURLConnection is great for getting a file from the web... It doesn't "wait" per se but its delegate callbacks:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
...allow you to be notified when data has been received and when the data has been completely downloaded. This way you can have the App show (if you like) a UIProgressBar as the data comes in and then handle the file as you please when it is completely received.

Resources