Search code examples
objective-cjsongraphshinobi

how to plot a Shinobi graph based on json data without key using objective c


I am having problem, plotting json data in this structure below.

{"response":{"hash":"0fea72f2bea9820c18227a655b42fe66","resp_code":"GRAPH_RETRIEVED","code":200},"resultstats":{"record_count":46},"ana_uoms":["°C"],"data":[{"asset_id":204,"company_id":30,"asset_name":"WIF","stats":{"min":1.4,"max":6.9,"min_tstamps_count":1,"min_tstamps":["2015-03-17 08:30:00"],"max_tstamps":["2015-03-17 11:00:00","2015-03-17 11:30:00","2015-03-17 13:40:00","2015-03-17 14:50:00"],"mkt":5.91,"max_tstamps_count":4,"avg":5.8},"component_type":"ana_in","component_description":"WFt","site_name":"Kll","alarms":[],"sampling_rate":10,"region_name":"ll","component_id":8340,"company_name":"lb","uom":"°C","uom_decimal_places":1,"unit_sn":"3310","resolves":[],"records":[["2015-03-17 08:00",2.6],["2015-03-17 08:10",3.9],["2015-03-17 08:20",2.4],["2015-03-17 08:30",1.4],["2015-03-17 08:40",3.1],["2015-03-17 08:50",4.4],["2015-03-17 09:00",5.1],["2015-03-17 09:10",5.5],["2015-03-17 09:20",6.1],["2015-03-17 09:30",6.2],["2015-03-17 09:40",5.3],["2015-03-17 09:50",6.4],["2015-03-17 10:00",6.6],["2015-03-17 10:10",6.7],["2015-03-17 10:20",6.8],["2015-03-17 10:30",5.2],["2015-03-17 10:40",6.3],["2015-03-17 10:50",6.7],["2015-03-17 11:00",6.9],["2015-03-17 11:10",6],["2015-03-17 11:20",6.6],["2015-03-17 11:30",6.9],["2015-03-17 11:40",5.9],["2015-03-17 11:50",6.6],["2015-03-17 12:00",6.8],["2015-03-17 12:10",6.1],["2015-03-17 12:20",6.6],["2015-03-17 12:30",5.6],["2015-03-17 12:40",6.2],["2015-03-17 12:50",6.8],["2015-03-17 13:00",5.7],["2015-03-17 13:10",6.6],["2015-03-17 13:20",5.8],["2015-03-17 13:30",6.4],["2015-03-17 13:40",6.9],["2015-03-17 13:50",6],["2015-03-17 14:00",6.7],["2015-03-17 14:10",5.2],["2015-03-17 14:20",6.5],["2015-03-17 14:30",5.8],["2015-03-17 14:40",6.3],["2015-03-17 14:50",6.9],["2015-03-17 15:00",6.6],["2015-03-17 15:10",5.9],["2015-03-17 15:20",6.3],["2015-03-17 15:30",6.5]]},{"asset_id":204,"company_id":30,"asset_name":"Wft","stats":{"min":2.9,"max":6.8,"min_tstamps_count":1,"min_tstamps":["2015-03-17 08:30:00"],"max_tstamps":["2015-03-17 11:00:00","2015-03-17 11:30:00","2015-03-17 12:00:00","2015-03-17 13:40:00"],"mkt":5.8,"max_tstamps_count":4,"avg":5.7},"component_type":"ana_in","component_description":"WIF Right Back","site_name":"Ktore","alarms":[],"sampling_rate":10,"region_name":"Kano","component_id":8341,"company_name":"lls","uom":"°C","uom_decimal_places":1,"unit_sn":"3310","resolves":[],"records":[["2015-03-17 08:00",3.2],["2015-03-17 08:10",4.2],["2015-03-17 08:20",3.1],["2015-03-17 08:30",2.9],["2015-03-17 08:40",3.7],["2015-03-17 08:50",4.5],["2015-03-17 09:00",5.2],["2015-03-17 09:10",5.6],["2015-03-17 09:20",6.1],["2015-03-17 09:30",6.3],["2015-03-17 09:40",4.8],["2015-03-17 09:50",6.3],["2015-03-17 10:00",6.5],["2015-03-17 10:10",6.6],["2015-03-17 10:20",6.7],["2015-03-17 10:30",4.5],["2015-03-17 10:40",6.3],["2015-03-17 10:50",6.6],["2015-03-17 11:00",6.8],["2015-03-17 11:10",5.9],["2015-03-17 11:20",6.5],["2015-03-17 11:30",6.8],["2015-03-17 11:40",5.7],["2015-03-17 11:50",6.5],["2015-03-17 12:00",6.8],["2015-03-17 12:10",5.9],["2015-03-17 12:20",6.6],["2015-03-17 12:30",5],["2015-03-17 12:40",6.2],["2015-03-17 12:50",6.7],["2015-03-17 13:00",5.5],["2015-03-17 13:10",6.5],["2015-03-17 13:20",5.2],["2015-03-17 13:30",6.2],["2015-03-17 13:40",6.8],["2015-03-17 13:50",5.8],["2015-03-17 14:00",6.6],["2015-03-17 14:10",4.5],["2015-03-17 14:20",6.4],["2015-03-17 14:30",5.2],["2015-03-17 14:40",6.2],["2015-03-17 14:50",6.7],["2015-03-17 15:00",6.4],["2015-03-17 15:10",5.2],["2015-03-17 15:20",6.2],["2015-03-17 15:30",6.1]]}],"ana_thresholds":[["<1.0"],[">8.0"]],"parameters":{"end_date":"2015-03-17 15:30","start_date":"2015-03-17 08:00","sampling_rate":10}}

I am basically trying to use Shinobi graph library trial to plot this json data but I am totally clueless how to parse objects above. In the json I have the date-time and temperature values. I manage to see the parse response in my console. However the graph has no object data to plot because I am not passing any json values to the series since I don't know how its done. Please kind assist because I have not seen a similar question in stackoverflow.

Here is my code snippet.

- (void) loadData{
// Parse units offline from the webservice.
@try{

    NSString *delete = [[NSString alloc] initWithFormat:@""];
    NSString *logOut = [NSString stringWithFormat:@"MY URL"];

    NSURL *url=[NSURL URLWithString:logOut];
    NSLog(@"Asset list: %@", url);
    NSData *postData =[delete dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
    NSString *postLength = [ NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"GET"];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
    [request setHTTPBody:postData];

    //[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[url host]];

    NSError *error = [[NSError alloc] init];
    NSHTTPURLResponse *response = nil;
    NSData *urlData=[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    NSString *responseData = [[NSString alloc]initWithData:urlData encoding:NSUTF8StringEncoding];

    NSLog(@"Reponse code: %ld", (long)[response statusCode]);
    if ([response statusCode] >= 200 && [response statusCode] < 300)
    {
        NSLog(@"Response ==> %@", responseData);
        @try{
            NSError *error = nil;
       // NSMutableArray* jsonDetails = [[NSMutableArray alloc]init];
            NSDictionary *jsonDetails = [NSJSONSerialization JSONObjectWithData:urlData options:NSJSONReadingMutableContainers|NSJSONReadingMutableLeaves error:&error];
            NSArray *graphData = [ jsonDetails objectForKey:@"records"];
             NSLog(@"Retrieving graph: %@", jsonDetails);

            for (NSDictionary* jsonPoint  in graphData) {
                SChartDataPoint* datapoint = [self dataPointForDate:jsonPoint[@"date"]
                                                           andValue:jsonPoint[@"temp"]];
                NSLog(@"SChart point: %@", datapoint);
                [_timeSeries addObject:datapoint];
            }
        }
        @catch (NSException *e){
            NSLog(@"Try catch block: %@", e);
        }
        @finally{
            // [self.tblRegion reloadData];
            NSLog(@"finally");
        }


    }

}
@catch (NSException * e) {
    NSLog(@"Exception: %@", e);

}

}


Solution

  • Thanks to sammyd's help, believe this a close answer to my question. The snippet below is almost perfect. The only thing is that I still need to change the dateformat to get the datapoints in the series.

    {
            NSLog(@"Response ==> %@", responseData);
            
                NSError *error = nil;
                jsonDetails = [NSJSONSerialization JSONObjectWithData:urlData options:kNilOptions error:&error];
            NSArray *keys = [jsonDetails allKeys];
            // values in foreach loop
            for (NSString *key in keys) {
                // NSLog(@"%@ is %@",key, [jsonDetails objectForKey:key]);
                
                data = [jsonDetails objectForKey:@"data"];
                graphData = [data[0]objectForKey:@"records"];
                datapoint = [[SChartDataPoint alloc] init];
                // NSLog(@"Record for the graph: %@", graphData);
                // results = [jsonDetails objectForKey:@"resultstats"];
                // recordCount = [results objectForKey:@"record_count"];
                
            for (int i=0; i< [graphData count]; i++){
                NSArray *record = graphData[i];
                // NSLog(@"Record value: %@", record);
                datapoint.xValue = record[0]; // date
                NSLog(@"Date/time: %@", datapoint.xValue);
                datapoint.yValue = record[1]; // number
                NSLog(@"Temp: %@", datapoint.yValue);
                datapoint = [self dataPointForDate:datapoint.xValue
                                                           andValue:datapoint.yValue];
                
                NSLog(@"Adding datapoint to series: %@", datapoint);
                [_timeSeries addObject:datapoint];
            }
               
            }
            
        }
    

    Here is the console out put. I'll not paste the whole console output because the json response and NSLog's I put for debugging purpose.You can see for some reason when I add datapoint objects to the series. datapoint.xValue is null hence I still don't see the graph in the app. I have changd the date format to yyyy-MM-dd HH:mm and here is my console output. Still no graph is plotted .

    TimeSeriesChart[952:468171] Adding datapoint to series: { index=0, x=2015-03-22 13:20:00 +0000, y=6.4, selected=N }
    2015-03-23 07:49:01.682 TimeSeriesChart[952:468171] Date/time: 2015-03-22 15:30
    2015-03-23 07:49:01.683 TimeSeriesChart[952:468171] Temp: 6.3
    2015-03-23 07:49:01.685 TimeSeriesChart[952:468171] Time/Date format: 2015-03-22 13:30:00 +0000
    2015-03-23 07:49:01.685 TimeSeriesChart[952:468171] Adding datapoint to series: { index=0, x=2015-03-22 13:30:00 +0000, y=6.3, selected=N }
    2015-03-23 07:49:01.697 TimeSeriesChart[952:468171] ShinobiCharts: Attempting to update axis data range with nil series min or max. Axis range not updated.
    From: SChartDateTimeAxis at 0x15d64d10, axisRange = { 0.000000, 1.000000 }, defaultRange = { 1970-01-01 00:00:00 +0000, 1970-01-01 00:00:01 +0000 }, maxRange = { 1970-01-01 00:00:00 +0000, 1970-01-01 00:00:01 +0000 }
    2015-03-23 07:49:01.698 TimeSeriesChart[952:468171] ShinobiCharts: Attempting to update axis data range with nil series min or max. Axis range not updated.
    From: SChartNumberAxis at 0x19c852e0, axisRange = { 0.000000, 1.000000 }, defaultRange = { 0.000000, 1.000000 }, maxRange = { 0.000000, 1.000000 }

    I fixed the above error by following sammyd's suggestion answer;

        for (NSArray *record in graphData) {
                
                // NSArray *record = graphData[i];
                // NSLog(@"Record value: %@", record);
                NSString *dateString = [NSString stringWithFormat:@"%@",[record objectAtIndex:0]];
                NSDate *date = [self dateFromString:dateString];
                datapoint.xValue = date; // date
                NSLog(@"Date/time: %@", datapoint.xValue);
                // NSString *date = datapoint.xValue;
                datapoint.yValue = record[1]; // number
                NSLog(@"Temp: %@", datapoint.yValue);
                datapoint = [self dataPointForDate:record[0]
                                                andValue:record[1]];
                
                NSLog(@"Adding datapoint to series: %@", datapoint);
                [_timeSeries addObject:datapoint];
            }
    

    I am now happy and proceeding to follow Sammayd's blog tutorial on implementing the randSammyD's Blog. See screenshots of the output. Thanks you all guys. enter image description here

    enter image description here

    In portrait the graph looks not so pretty any suggestions are welcome. Mind you the data plotted here is about 4000+ data.I think it can be better scaled, please share what I can do to make the graph more representable like the iOS stock App.