// // EQNManager.m // Earthquake Network // // Created by Luca Beretta on 17/09/18. // Copyright © 2018 Luca Beretta. All rights reserved. // #import "EQNManager.h" #import "EQNCalibrazione.h" #import "EQNRilevamento.h" #import "EQNUser.h" #import "Costanti.h" #import "ServerRequest.h" #import "EQNGeneratoreURLServer.h" #import "EQNPastquakes.h" #import "EQNSegnalazione.h" #import "EQNSisma.h" #import "EQNUtility.h" @interface EQNManager() @property (nonatomic, strong) EQNCalibrazione *calibrazione; @property (nonatomic, strong) NSDate *timeStamp; @property (nonatomic, strong) NSDate *lastSeismicUpdate; @property (nonatomic, assign) BOOL inCalibrazione; @property (nonatomic, assign) BOOL inRilevamento; @end @implementation EQNManager #pragma mark - Singleton + (instancetype)defaultManager { static EQNManager *instance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); return instance; } #pragma mark - Init - (instancetype)init { self = [super init]; if (self) { self.retiSismiche = [EQNUtility loadArrayOfClass:[EQNSisma class] fromUserDefaultsForKey:EQNUserDefaultSeismicNetworkCards]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForegroundNotification:) name:UIApplicationWillEnterForegroundNotification object:nil]; } return self; } #pragma mark - Private - (void)scaricaDatiReteSmartphone { [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:EQNServerUrlDownloadSmartphoneNetwork] richiesta:EQNTipoChiamataDownloadDati success:^(id result) { self.rete_smartphone = [[EQNReteSmartphone alloc] initWithInfo:result]; [self performSelectorOnMainThread:@selector(scaricaAreaCheck) withObject:nil waitUntilDone:YES]; } failure:^(NSError * error) { NSLog(@"[EQNManager] Download dati rete smartphone fallito. Errore: %@", error.localizedDescription); }]; } - (void)scaricaAreaCheck { [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@?lat=%f&lon=%f", EQNServerUrlDownloadAreaCheck, [EQNUser defaultUser].lastPosition.coordinate.latitude, [EQNUser defaultUser].lastPosition.coordinate.longitude]] richiesta:EQNTipoChiamataAreaCheck success:^(id result) { self.area_check = [[EQNAreaCheck alloc] initWithInfo:result]; [self performSelectorOnMainThread:@selector(scaricaPastquakes) withObject:nil waitUntilDone:YES]; } failure:^(NSError * error) { NSLog(@"[EQNManager] Download area check fallito. Errore: %@", error.localizedDescription); }]; } - (void)scaricaPastquakes { [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:EQNServerUrlDownloadPastQuakes] richiesta:EQNTipoChiamataPastquakes success:^(id result) { NSMutableArray *array = [NSMutableArray array]; NSArray *tempArray = (NSArray *)result; for (NSDictionary *dic in tempArray) { [array addObject:[[EQNPastquakes alloc] initWithDictionary:dic]]; } self.datiPastQuakes = [NSArray arrayWithArray:array]; [self performSelectorOnMainThread:@selector(scaricaSegnalazioniManuali) withObject:nil waitUntilDone:YES]; } failure:^(NSError * error) { NSLog(@"[EQNManager] Download pastquakes fallito. Errore: %@", error.localizedDescription); }]; } - (void)scaricaSegnalazioniManuali { [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[NSURL URLWithString:EQNServerUrlDownloadUserReports] richiesta:EQNTipoChiamataSegnalazioneManuale success:^(id result) { NSMutableArray *array = [NSMutableArray array]; NSArray *tempArray = (NSArray *)result; for (NSDictionary *dict in tempArray) { [array addObject:[[EQNSegnalazione alloc] initWithDictionary:dict]]; } self.elencoSelagnazioniManuali = [NSArray arrayWithArray:array]; [self performSelectorOnMainThread:@selector(scaricaReteSismica) withObject:nil waitUntilDone:YES]; } failure:^(NSError * error) { NSLog(@"[EQNManager] Download segnalazioni manuali. Errore: %@", error.localizedDescription); }]; } - (void)scaricaReteSismica { // Per ridurre i dati trasferiti tra app e server, ci sono degli endpoint dedicati // in base alla magnitudo impostata dall'utente (per valori inferiori a 2.0). // Se l'opzione `Mostra sismi di qualsiasi magnitudo se a meno di 50km` è attiva, // dobbiamo utilizzare l'endpoint `_M0_0` perchè dobbiamo scaricare tutti i dati NSString *queryString = @""; double filterMagnitude = [[EQNSeismic shared].magnitudoMinima doubleValue]; bool filterAnyNearEarthquake = [EQNSeismic shared].sismiQualsiasiAbilitati; if (filterMagnitude < 0.5 || filterAnyNearEarthquake) { queryString = @"_M0_0"; } else if (filterMagnitude < 1.0) { queryString = @"_M0_5"; } else if (filterMagnitude < 1.5) { queryString = @"_M1_0"; } else if (filterMagnitude < 2.0) { queryString = @"_M1_5"; } else { // verrà usato l'url base queryString = @""; } NSString *urlString = [NSString stringWithFormat:EQNServerUrlDownloadRetiSismiche, queryString]; NSURL *url = [NSURL URLWithString:urlString]; NSLog(@"[EQNManager] Url utilizzato per download reti sismiche: %@", url.absoluteURL); [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:url richiesta:EQNTipoChiamataDownloadDati success:^(id result) { NSMutableArray *array = [NSMutableArray array]; for (NSDictionary *dic in result) { [array addObject:[[EQNSisma alloc] initWithInfo:dic]]; } self.retiSismiche = [NSArray arrayWithArray:array]; self.lastSeismicUpdate = [NSDate date]; [EQNUtility storeArray:array toUserDefaultForKey:EQNUserDefaultSeismicNetworkCards]; [[NSNotificationCenter defaultCenter] postNotificationName:EQNDownloadDataDidCompleteNotification object:nil userInfo:nil]; } failure:^(NSError * error) { NSLog(@"[EQNManager] Download reti sismiche fallito. Errore: %@", error.localizedDescription); }]; } #pragma mark - Notifications - (void)applicationWillEnterForegroundNotification:(NSNotification *)notification { [self refreshSeismicDataForced:NO]; } #pragma mark - Public - (void)sincronizza { [self scaricaDatiReteSmartphone]; } - (void)refreshSeismicDataForced:(BOOL)forced { if (forced || self.lastSeismicUpdate == nil) { [self sincronizza]; } else { // scarico i dati solo se è passato più del tempo di refresh previsto NSTimeInterval difference = [[NSDate date] timeIntervalSinceDate:self.lastSeismicUpdate]; if (difference > EQNSeismicDataRefreshInterval) { [self sincronizza]; } } } - (void)avviaManager { self.isBackground = YES; self.timeStamp = [NSDate date]; } - (void)stopManager { self.isBackground = NO;; self.timeStamp = nil; } - (void)controllaStatoApplicazione { [[UIDevice currentDevice] setBatteryMonitoringEnabled:YES]; switch ([[UIDevice currentDevice] batteryState]) { case UIDeviceBatteryStateUnknown: [EQNUser defaultUser].inCarica = NO; break; case UIDeviceBatteryStateUnplugged: [EQNUser defaultUser].inCarica = NO; break; case UIDeviceBatteryStateCharging: [EQNUser defaultUser].inCarica = YES; break; case UIDeviceBatteryStateFull: [EQNUser defaultUser].inCarica = YES; break; default: break; } NSLog(@"Loanciato controllo batteria "); if ([EQNUser defaultUser].inCarica){ NSTimeInterval timer = [[NSDate date] timeIntervalSinceDate:self.timeStamp]; NSLog(@"Timer %f", timer); if (!self.calibrazione) { if (!self.inCalibrazione) { if(timer > TEMPO_LATENZA_CALIBRAZIONE){ [[NSNotificationCenter defaultCenter] postNotificationName:EQNDebugLogWillUpdateNotification object:nil userInfo:@{@"messaggio": @"Avvio Calibrazione"}]; NSLog(@"Avvio Calibrazione"); self.inCalibrazione = YES; [self avviaCalibrazione]; } } } else { if(timer > TEMPO_RIPETIZIONE_CALIBRAZIONE){ [self annullaCalibrazione]; self.inCalibrazione = YES; [self avviaCalibrazione]; } if (!self.inRilevamento && self.calibrazione.stato == calibrato) { [self avviaRilevamento]; } } } else { [self annullaCalibrazione]; } } - (void)avviaCalibrazione { [EQNCalibrazione startCalibrazione:^(EQNCalibrazione *cal) { self.calibrazione = cal; NSLog(@"Media %f stato %li", cal.media, (long)cal.stato ); [self performSelectorOnMainThread:@selector(iniviaMessaggioAlServer:) withObject:nil waitUntilDone:YES]; [[NSNotificationCenter defaultCenter] postNotificationName:EQNDebugLogWillUpdateNotification object:nil userInfo:@{@"messaggio": [NSString stringWithFormat:@"Media %f stato %li", cal.media, (long)cal.stato ]}]; if (self.calibrazione.stato == nonCalibrato){ self.inCalibrazione = YES; [self performSelectorOnMainThread:@selector(avviaCalibrazione) withObject:nil waitUntilDone:YES]; }else{ self.inCalibrazione = NO; [self performSelectorOnMainThread:@selector(avviaRilevamento) withObject:nil waitUntilDone:YES]; } }]; } - (void)annullaCalibrazione { self.calibrazione = nil; self.inRilevamento = NO; self.inCalibrazione = NO; self.timeStamp = [NSDate date]; } - (void)avviaRilevamento { if (self.calibrazione) { self.inRilevamento = YES; [EQNRilevamento startRilevamentoWithCalibrazione:self.calibrazione result:^(EQNRilevamento *ril) { NSLog(@"Rilevamento data %@ stato %li deviaizone %f ", ril.timestamp, (long)ril.rilievo, ril.deviazione); [[NSNotificationCenter defaultCenter] postNotificationName:EQNDebugLogWillUpdateNotification object:nil userInfo:@{@"messaggio": [NSString stringWithFormat:@"Rilevamento data %@ stato %li deviaizone %f deviazione calibrazione %f", ril.timestamp, (long)ril.rilievo, ril.deviazione, self.calibrazione.deviazione]}]; if (ril == NULL){ [self performSelectorOnMainThread:@selector(avviaCalibrazione) withObject:nil waitUntilDone:YES]; return; } switch (ril.rilievo) { case EQNRilevamentoSogliaPositivo:{ [self performSelectorOnMainThread:@selector(iniviaMessaggioAlServer:) withObject:ril waitUntilDone:YES]; self.calibrazione = nil; } break; case EQNRilevamentoSogliaNegativo: /* [self performSelectorOnMainThread:@selector(riavviaRilevamento) withObject:nil waitUntilDone:YES];*/ self.inRilevamento = NO; break; default: break; } }]; } } - (void)riavviaRilevamento { if (self.calibrazione) { [self avviaRilevamento]; } } - (void)iniviaMessaggioAlServer:(EQNRilevamento *)anRilevamento { EQNTipoChiamata tipo = EQNTipoChiamataCalibrazione; EQNCalibrazione *anCalibrazione = [self.calibrazione copy]; if (anRilevamento.rilievo == EQNRilevamentoSogliaPositivo){ tipo = EQNTipoChiamataRilevamento; [self annullaCalibrazione]; } [[ServerRequest defaultServerConnectionSingleton] inviaInformazioniAlServerWithURL:[EQNGeneratoreURLServer urlMessagioStatoSmartPhone:anCalibrazione rilevamento:anRilevamento] richiesta:tipo success:^(id result) { [[NSNotificationCenter defaultCenter] postNotificationName:EQNDebugLogWillUpdateNotification object:nil userInfo:@{@"messaggio": [NSString stringWithFormat:@"invio informazione al server tipo %ld inviato ", (long)tipo]}]; } failure:^(NSError *error) { [[NSNotificationCenter defaultCenter] postNotificationName:EQNDebugLogWillUpdateNotification object:nil userInfo:@{@"messaggio": [NSString stringWithFormat:@"invio informazione al server tipo %ld fallito ", (long)tipo]}]; }]; } @end