Send and receive key/value pair using gcdasyncsocket over wifi - ios

I've made an iOS app that receives RSSI values from a BLE Beacon and sends (using GCDAsynSocket) it to a connected MacBook over wifi. My next app on the MacBook receives the RSSI values and saves (using NSOutpuStream class) it in .txt format.
Now, I need to send RSSI values from eight different BLE beacons and their respective MAC address in key/value pairs.
I tried to solve it using NSKeyedArchiver to encode NSDictionary into NSData.
NSData *data = [NSKeyedArchiver archivedDataWithRootObject: NSDictionaryContaningKeyValuePair];
And on the receiver's end (MacBook), I used NSUnarchiver to decode. I am unable to extract the NSDictionary containing key/value (MAC address/RSSI values) pair and store it to the .txt file. Moreover, since NSoutputStrteam write method takes nonnull const uint8_t value, how can I write the Key/value pair in the .txt file?
I use Objective-C and Xcode (7.0).
Thank you.

Got the solution. NSDictionary can be sent using NSJSONSerialization class. At transmitter's end (iOS):
NSDictionary* dictInfo = [NSDictionary dictionaryWithObjectsAndKeys:self.txtInfo.text,#"data", nil];
NSData* dataDict = [NSJSONSerialization dataWithJSONObject:dictInfo options:NSJSONWritingPrettyPrinted error:nil];
[self.socket writeData:dataDict withTimeout:-1.0f tag:0];
At receiver's end (MacBook):
if ([self getSelectedSocket]== sock) {
[_dataBuffer appendData:data];
if ([sock socketAvailableBytes] == 0) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:_dataBuffer options:NSJSONReadingMutableLeaves error:nil];
DLog("Dictionary Info: %#", dict);
NSString* strInfo = (NSString*)[dict objectForKey:#"data"];
[_dataBuffer setLength:0];
self.txtLogs.stringValue= strInfo;
For further information please visit https://github.com/boobalaninfo/Bonjour-iOS-MAC-Apps.

Related

WatchConnectivity attempting to send data to Watch app

I'm trying to send data from my iOS app to the Watch app. I'm using the updateApplicationContext for this.
I have a json file that I converted in NSDictionary and tried to send it. But there is an error, here it is:
[WCSession updateApplicationContext:error:]_block_invoke failed due to WCErrorCodePayloadUnsupportedTypes
The file is correctly read.
Now here is the code that tries to send the data.
NSString *fileName = [[NSBundle mainBundle] pathForResource:#"data"
ofType:#"json"];
NSLog(fileName);
if (fileName) {
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:fileName];
NSDictionary *data = [NSJSONSerialization JSONObjectWithData:jsonData
options:0
error:&error];
if (error) {
NSLog(#"Something went wrong! %#", error.localizedDescription);
}
else {
NSLog(#"Rsens info: %#", data);
[WatchSessionManager.sharedManager updateApplicationContextWithApplicationContext:#{#"json": data} error:&error];
}
}
else {
NSLog(#"Couldn't find file!");
}
I read somewhere that the types that we could send were limited, but the dictionary was allowed. I'm sending a dictionary though.
Can you find what is the error?
[SOLUTION]
I found out that there were values of type long in my dictionary. In my JSON I had some properties that were transtyped in type long. Here is one of the properties before:
"state": 0
I just put my numbers in string quotes.
"state":"0"
Check the dictionary's content.
WatchConnectivity dictionaries can only contain property list types.

Sending NSDATA from 32bit to 64bit in multiplayer game using Game centre in ios

I am developing multiplayer game using game centre, Overall Code is working well if my both device is 64bit or 32bit, but if my one device is 32bit and other is 64bit than sending data is not correct, please help me,
thanks in Advance
- (void)sendDataToPlayers:(void *)data length:(NSInteger)length
{
NSError *error = nil;
NSLog(#"lenth %i",(int)data);
NSData *package = [NSData dataWithBytes:data length:length];
[self.currentMatch sendDataToAllPlayers:package withDataMode:GKMatchSendDataReliable error:&error];
[self setLastError:error];
}
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID
{
[self.transportDataDelegate onReceivedData:data fromPlayer:playerID];
}
You could for example look at NSJSONSerialization, which allows you to convert any dictionary or array containing dictionaries, arrays, numbers, strings, and NSNull values to NSData in a 100% portable way. There is one method turning dictionary or array into NSData, and another to turn NSData back into the exact same dictionary or array.
I Solved this problem, by changing the formate of data packet, i was sending user define struct which has different data types like integers and char when this send to the other player and decode from NSdata its receives nothing like zeros and null,
i change my packet formate like now i am sending NSString,
NSString *moveString =[ NSString stringWithFormat:#"/,%i,%i,%i,%i",oMoveMade.getFrom(),oMoveMade.getTo(),oMoveMade.getFromsquare(),oMoveMade.getTosquare()];
NSString *temp = [ NSString stringWithFormat:#"%i,", oMoveMade.getFrom()];
[moveString stringByAppendingString:temp];
[moveString stringByAppendingString:[ NSString stringWithFormat:#"%i,",oMoveMade.getTo()]];
[moveString stringByAppendingString:[ NSString stringWithFormat:#"%i,", oMoveMade.getFromsquare()]];
[moveString stringByAppendingString:[ NSString stringWithFormat:#"%i", oMoveMade.getTosquare()]];
NSLog(#"movestring %#",moveString);
NSData *package = [moveString dataUsingEncoding:NSUTF8StringEncoding];
[self.currentMatch sendDataToAllPlayers:package withDataMode:GKMatchSendDataReliable error:&error];
this is not exactly solution but in my case its solved my problem, if some one has better solution most welcome to help us

Serialize an unsigned long long using NSJSONSerialization

I have a REST API which expects a file size field to be in bytes. However I am observing that NSJSONSerialization is converting my value to an exponential representation which my server doesn't support.
For example:
unsigned long long fileSize = 100000000000;
NSDictionary *myObject = #{"fileSize": #(fileSize)};
NSData *dataToSend = [NSJSONSerialization dataWithJSONObject:myObject options:0 error:nil];
// send dataToSend to network
On the wire I observe the following is sent:
{ "fileSize" : 1.0e+11 }
Is there any way to force NSJSONSerialization to retain the unsigned long long formatting on the wire?
E.g.
{ "fileSize" : 100000000000 }
Update: Corrected my sample code thanks to Gabriele Petronella
Turns out I was able to solve this just now by explicitly initializing the NSNumber as an unsigned long long.
E.g.
unsigned long long fileSize = 100000000000;
NSDictionary *myObject = #{"fileSize": [NSNumber numberWithUnsignedLongLong:fileSize]};
NSData *dataToSend = [NSJSONSerialization dataWithJSONObject:myObject options:0 error:nil];
// send dataToSend to network
This resulted in the output I expected:
{ "fileSize" : 100000000000 }
I don't see any NSJSONSerialization in your question, anyway converting the dictionary to a NSData instance seems wrong, and it's likely to be causing this encoding issue. Just do something like
NSDictionary *myObject = #{"fileSize": #(fileSize)};
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myObject options:0 error:nil];

Adding a JSON blob to a JSON request in iOS

I need to be able to create a JSON object (I'm using the built in classes in iOS 5).
The JSON that should be sent is this:
{"request_type":"<the request type (a string)>" "security_level":<the security level (an int)> "device_type":"<android or ios (a string)" "version":<the app version (android, ios on different version schemes) (a float)> "email":<the email address of the user sending the request (a string)> "blob":{<the contents of the actual request, encrypted/encoded according to the security level (a map)>}
My problem is with the last portion, a "blob"
Which is basically just another JSON object, i.e.
{"display_name":"Jack Bower", "email":"jackb#gmail.com", "password":"roflcopter"}
(Let's forget the password is in plaintext)
I can create everything using NSDictionary,
I just don't know how to add the last part.
My guess is create the first request using NSDictionary.
Then create the second blob request using another NSDictionary.
And then just add that second blob NSDictionary as a object back to the initial NSDictionary.
Will NSJSONSerialization understand what I'm trying to do?
Ok I think it's 5am and I'm just being really stupid:
here's the answer:
NSDictionary *blobData = [NSDictionary dictionaryWithObjectsAndKeys:
#"email",userEmail,
#"password",userPassword,
nil];
NSString *blobString = [[NSString alloc]
initWithData:[NSJSONSerialization dataWithJSONObject:blobData options:kNilOptions error:&error]
encoding:NSUTF8StringEncoding];
NSDictionary *requestData = [NSDictionary dictionaryWithObjectsAndKeys:
#"login",#"request_type",
0,#"security_level",
#"ios",#"device_type",
#"blob",blobString,
nil];
NSData *JSONRequestData = NULL;
if ([NSJSONSerialization isValidJSONObject:requestData]) {
NSData *JSONRequestData = [NSJSONSerialization dataWithJSONObject:requestData options:kNilOptions error:&error];
}
else NSLog(#"requestData was not a proper JSON object");

NSJSONSerialization from NSString

Is it possible if I have a NSString and I want to use NSJSONSerialization? How do I do this?
First you will need to convert your NSString to NSData by doing the following
NSData *data = [stringData dataUsingEncoding:NSUTF8StringEncoding];
then simply use the JSONObjectWithData method to convert it to JSON
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
You need to convert your NSString to NSData, at that point you can use the +[NSJSONSerialization JSONObjectWithData:options:error:] method.
NSString * jsonString = YOUR_STRING;
NSData * data = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError * error = nil;
id json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (!json) {
// handle error
}
You can convert your string to NSData by saying:
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
You can then use it with NSJSONSerialization. Note however that NSJSONSerialization is iOS5 only, so you might be better off using a library like TouchJSON or JSONKit, both of which let you work directly with strings anyway, saving you the step of converting to NSData.
I wrote a blog post that demonstrates how to wrap the native iOS JSON class in a general protocol together with an implementation that use the native iOS JSON class.
This approach makes it a lot easier to use the native functionality and reduces the amount of code you have to write. Furthermore, it makes it a lot easier to switch out the native implementation with, say, JSONKit, if the native one would prove to be insufficient.
http://danielsaidi.com/blog/2012/07/04/json-in-ios
The blog post contains all the code you need. Just copy / paste :)
Hope it helps!

Resources