ShiCaoPeriodVC.m 153 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727
  1. //
  2. // ShiCaoPeriodVC.m
  3. // jiaPei
  4. //
  5. // Created by apple on 2017/2/7.
  6. // Copyright © 2017年 JCZ. All rights reserved.
  7. //
  8. #define SCReenBRIGHTTIME 300
  9. #define SCREENBRIGHTLOWST 0.3
  10. #import "ShiCaoPeriodVC.h"
  11. #import "ScanVC.h"
  12. #import <CoreLocation/CoreLocation.h>
  13. #import "Evaluation.h"
  14. //#import "APViewController.h"
  15. #import "AllLightImagePickerController.h"
  16. #import "ShiCaotableView.h"
  17. #import <BaiduMapAPI_Map/BMKMapComponent.h>//引入地图功能所有的头文件
  18. #import <BMKLocationkit/BMKLocationComponent.h>//引入定位功能所有的头文件
  19. #import <BaiduMapAPI_Utils/BMKUtilsComponent.h>//bd计算相关
  20. //蓝牙
  21. #import <CoreBluetooth/CoreBluetooth.h>
  22. @interface ShiCaoPeriodVC ()<BMKLocationManagerDelegate,CLLocationManagerDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate,UITableViewDelegate,UITableViewDataSource,UIGestureRecognizerDelegate,CBCentralManagerDelegate,CBPeripheralDelegate>
  23. {
  24. NSMutableArray *detailLabArr;
  25. UILabel *timeLabel;
  26. UIButton *on_offBtn;
  27. UIView *backView;//计时结束弹框
  28. NSTimer *timer;
  29. //trainview
  30. UIView *trainView;
  31. UITableView *mainTableView;//trainview addsubview maintableview
  32. NSMutableArray *trainViewLabs;
  33. UILabel *bgLabel;
  34. //注意事项
  35. UIView *noticeView;
  36. UIButton *isForeverBtn;
  37. NSMutableDictionary *minuteTrainDic;//分钟学时用参数 签到和断线重连时候初始化 分钟学时发送之前更新字典
  38. NSMutableDictionary *gatherTrainDic;//汇总学时用参数 签到和断线重连时候初始化 分钟学时发送之前更新字典 并存本地 短线重连用来恢复计时
  39. NSArray *minuteTrainArray;//分钟学时数组 用于汇总学时时候 获取本地库未上传的分钟学时
  40. NSDictionary *scanDic;//扫描二维码获取到的数据
  41. NSArray *coachdataArray;//教练数据
  42. NSMutableArray *gpsArray;
  43. NSString *classId; //课堂ID
  44. NSString *classCode; //课程编码
  45. NSString *trainNum; //学时编号
  46. NSString *trainOrderNum;//学时编号用序列 每天置0
  47. BOOL isPlanPeriod; //是否是计划计时
  48. NSString *orderId; //订单ID
  49. NSInteger seconds; //定时器时间
  50. NSDictionary *finishDataDic; //汇总完毕 服务器返回数据
  51. BOOL isVoice; //是否开启语音提醒 默认开启
  52. NSMutableArray<NSString *> *dataSourceArray; //表的数据源 组成部分:颜色数字+提示字 1为红色失败 2为绿色成功
  53. BOOL isImitate; //是否正在模拟计时
  54. BOOL isTerminal; //是否是终端实操计时
  55. BOOL isForceKeYi; //是否集中理论学习
  56. //拍照倒计时
  57. UIButton *countDownBtn;
  58. UIView *countDownView;
  59. NSInteger photoTime;
  60. BOOL isSubjectTwoSignIn;
  61. //签到拍照
  62. NSTimer *signInTimer;
  63. //地图定位
  64. BMKLocationManager *baiduLocationMan;
  65. CLLocationCoordinate2D myCoordinate;
  66. NSMutableDictionary *gpsDic; //某个点的信息
  67. NSDictionary *lastGPSDic; //上个点的信息 用于计算累加里程
  68. CGFloat mileageFloat;//累加里程 每分钟置为0.0000
  69. CLLocationManager *locationManager;//系统gps
  70. //系统参数
  71. NSInteger startPhotoTime;//拍照开始时间
  72. NSInteger endPhotoTime;//拍照结束时间
  73. NSInteger systemMaxSpeed;//最大速度限制
  74. //计时省电相关
  75. CGFloat _scrStartBright;//记录屏幕初始亮度
  76. NSInteger _scrBrtTime;//进入省电模式前的时间
  77. BOOL _flag;//判断是否是非学员操作(代码修改)变化的屏幕亮度
  78. //蓝牙相关
  79. NSString *peripheralName;//蓝牙名称
  80. BOOL dataIsLack;//如果为yes代表数据不完整 需要下次接收到的数据拼接
  81. NSString *lastData;//接收蓝牙数据时 一个数据包分次返回时 之前的数据
  82. NSString *blueToothOrder;//最新的蓝牙命令 用于蓝牙未回应重新作操作
  83. NSInteger reOrderCount;//蓝牙重新请求的次数 如果大于三次 不继续请求 接收到回应就重置 防治无限请求蓝牙
  84. NSInteger bTRequestTime;//蓝牙响应时间 主要用于拍照相关命令 如果超过三秒 没回应 重新发拍照命令
  85. NSInteger orderNum;//图片分包数
  86. NSString *imageData;//图片数据
  87. NSInteger imgLongth;//图片的总长度 或者每个包的长度
  88. NSInteger lastLongth;//最后一个包的长度
  89. BOOL isLastOrder;//是否是获取最后一个包的命令
  90. BOOL isConnectBlueTooth;//是否与蓝牙连接状态
  91. NSInteger disconnectSeconds;//蓝牙断开的时长
  92. NSInteger heartSeconds;//心跳包间隔时间 每次心跳命令清零 如果大于180 则视为非法蓝牙连接
  93. BOOL isNeedSignIn; //蓝牙心跳包验证中是否需要签到 只有在扫描完二维码的时候 将该值设置为YES yes的时候需要签到
  94. BOOL stopReplyHeart;//停止回复心跳包验证 获取OBD数据和拍照前三秒置为yes 不与心跳包交互
  95. NSInteger takePhotoFailCount;//人脸比对失败次数 超过三次会停止计时
  96. BOOL isNotPlayAudio;
  97. }
  98. //蓝牙
  99. @property (nonatomic, strong) CBCentralManager *cbcManager;
  100. /** 已连接的外设*/
  101. @property (nonatomic, strong) CBPeripheral *peripheral;
  102. /** 要写入的特征值*/
  103. @property (nonatomic, strong) CBCharacteristic *writeCharacteristic;
  104. /** 要读的特征值*/
  105. @property (nonatomic, strong) CBCharacteristic *readCharacteristic;
  106. @property (nonatomic, strong) UILabel *blueToothLabel;
  107. @property (nonatomic, strong) UIImageView *photoImg;
  108. @end
  109. @implementation ShiCaoPeriodVC
  110. - (void)viewDidLoad {
  111. [super viewDidLoad];
  112. self.title = @"实操计时";
  113. self.view.backgroundColor = backGroundColor;
  114. _haveBlueTooth = NO;
  115. isForceKeYi = NO;
  116. isImitate = NO;
  117. isTerminal = NO;
  118. gatherTrainDic = nil;
  119. coachdataArray = [NSArray new];//初始化教练数据
  120. isSubjectTwoSignIn = NO;
  121. isNeedSignIn = NO;
  122. isConnectBlueTooth = NO;
  123. isNotPlayAudio = NO;
  124. //屏幕亮度相关
  125. _scrStartBright = [[UIScreen mainScreen] brightness];
  126. _scrBrtTime = SCReenBRIGHTTIME;
  127. _flag = NO;
  128. UIBarButtonItem* backBbi = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"backIcon.png"] style:UIBarButtonItemStylePlain target:self action:@selector(goBackByNavigation)];
  129. [self.navigationItem setLeftBarButtonItem:backBbi];
  130. CGFloat varY = 0;
  131. detailLabArr = [NSMutableArray new];
  132. for (int i=0; i<3; i++) {
  133. CGFloat wid = kSize.width-50;
  134. UILabel *detailLab;
  135. detailLab = [[UILabel alloc]initWithFrame:CGRectMake(25+wid*(0.4+(i-1)*0.3), varY, wid*0.3, 40)];
  136. [detailLab setText:@"" Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  137. if (i==0) {
  138. detailLab = [[UILabel alloc]initWithFrame:CGRectMake(25, varY, wid*0.4, 40)];
  139. [detailLab setText:@"" Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  140. }
  141. [self.view addSubview:detailLab];
  142. [detailLabArr addObject:detailLab];
  143. }
  144. varY += 10 + 40;
  145. timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(25, varY, kSize.width - 50, kSize.width/3.0)];
  146. timeLabel.backgroundColor = [UIColor whiteColor];
  147. [timeLabel borderColor:RQlineColor width:2 cornorRadius:10];
  148. [timeLabel setText:@"00:00:00" Font:44 TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  149. [self.view addSubview:timeLabel];
  150. //开启关闭语音
  151. isVoice = YES;
  152. dataSourceArray = [NSMutableArray array];
  153. varY += 20+kSize.width/3.0;
  154. trainView = [[UIView alloc] initWithFrame:CGRectMake(0, varY, kSize.width, kSize.height - varY - kNavOffSet - 50 - kSafeAreaBottomHeight)];
  155. trainView.backgroundColor = backGroundColor;
  156. [self.view addSubview:trainView];
  157. trainView.hidden = YES;
  158. varY = 0;
  159. // trainViewLabs = [NSMutableArray new];
  160. // NSArray * labtitles = @[@"当前计时时长",@"总时长",@"需要时长"];
  161. // CGFloat labWid = (kSize.width-30)/3;
  162. // for (int i=0; i<labtitles.count; i++) {
  163. // UILabel * lab = [[UILabel alloc]initWithFrame:CGRectMake(15+labWid*i, varY, labWid, 30)];
  164. //// lab.backgroundColor = [UIColor whiteColor];
  165. // [lab setText:labtitles[i] Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  166. // [trainView addSubview:lab];
  167. //
  168. // UILabel * labBtom = [[UILabel alloc]initWithFrame:CGRectMake(15, varY+30, labWid, 30)];
  169. // labBtom.backgroundColor = [UIColor whiteColor];
  170. // [labBtom setText:labtitles[i] Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  171. // [trainView addSubview:labBtom];
  172. // [trainViewLabs addObject:labBtom];
  173. // }
  174. //
  175. // for (int i=0; i<2; i++) {
  176. // UIView *trainVLine = [[UIView alloc]initWithFrame:CGRectMake(15+labWid*(i+1), 0, 1, 60)];
  177. // trainVLine.backgroundColor = RGB_COLOR(230, 230, 230);
  178. // [trainView addSubview:trainVLine];
  179. // }
  180. //
  181. // UIView *trainVLine2 = [[UIView alloc]initWithFrame:CGRectMake(15, 30, kSize.width-30, 1)];
  182. // trainVLine2.backgroundColor = RGB_COLOR(230, 230, 230);
  183. // [trainView addSubview:trainVLine2];
  184. //
  185. // varY = 60;
  186. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(kSize.width - 75 - 80 - 10, varY, 80, 30)];
  187. [label setText:@"语音提示" Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentRight];
  188. [trainView addSubview:label];
  189. UISwitch *switchButton = [[UISwitch alloc] initWithFrame:CGRectMake(kSize.width - 75, varY, 50, 30)];
  190. [switchButton setOn:YES];
  191. [switchButton addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged];
  192. [trainView addSubview:switchButton];
  193. label = [[UILabel alloc] initWithFrame:CGRectMake(25, varY, kSize.width/2.0 - 25, 30)];
  194. [label setText:@"学时上传记录" Font:FontLarger TextColor:kTitleColor];
  195. [trainView addSubview:label];
  196. varY += 30+10;
  197. [label addViewWithRect:CGRectMake(20, varY - 1, kSize.width - 40, 1)];
  198. mainTableView = [[ShiCaotableView alloc] initWithFrame:CGRectMake(0, varY, kSize.width, trainView.height - varY) style:UITableViewStylePlain];
  199. mainTableView.delegate = self;
  200. mainTableView.dataSource = self;
  201. mainTableView.rowHeight = 40;
  202. mainTableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
  203. [trainView addSubview:mainTableView];
  204. varY = kSize.height - kNavOffSet - 50 - kSafeAreaBottomHeight;
  205. on_offBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  206. on_offBtn.frame = CGRectMake(0, varY, kSize.width, 50);
  207. if ([RQ_USER_MANAGER.currentUser.city isEqualToString:@"3501"]) {//福州。。。
  208. [on_offBtn setTitle:@"签到计时" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  209. }else if ([RQ_USER_MANAGER.currentUser.city isEqualToString:@"3502"]) {//厦门
  210. [on_offBtn setTitle:@"签到计时" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  211. } else{
  212. [on_offBtn setTitle:@"开始计时" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  213. }
  214. on_offBtn.backgroundColor = RQ_MAIN_COLOR;
  215. // [on_offBtn borderColor:RQ_MAIN_COLOR width:2 cornorRadius:5];
  216. [on_offBtn target:self tag:1];
  217. [self.view addSubview:on_offBtn];
  218. on_offBtn.hidden = YES;
  219. //定位功能
  220. //开启百度定位
  221. baiduLocationMan = [[BMKLocationManager alloc]init];
  222. baiduLocationMan.delegate = self;
  223. //设置返回位置的坐标系类型 默认为国标
  224. baiduLocationMan.coordinateType = BMKLocationCoordinateTypeBMK09LL;//百度经纬度坐标
  225. //获取服务器学员状态
  226. [self getStuSignFlag];
  227. //获取系统参数
  228. startPhotoTime = 10;
  229. endPhotoTime = 30;
  230. systemMaxSpeed = 60;
  231. for (ParamsItem *item in RQ_USER_MANAGER.currentUser.params) {
  232. if ([item.KEY isEqualToString:@"SP_START_SHOOT_TIME"]) {
  233. NSString * str = item.VALUE;
  234. startPhotoTime = [str integerValue];
  235. }else if ([item.KEY isEqualToString:@"SP_END_SHOOT_TIME"]){
  236. NSString * str = item.VALUE;
  237. endPhotoTime = [str integerValue];
  238. }else if ([item.KEY isEqualToString:@"SP_MAX_SPEED"]) {
  239. NSString * str = item.VALUE;
  240. systemMaxSpeed = [str floatValue];
  241. }
  242. }
  243. if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"isShowNotice"] isKindOfClass:[NSString class]]) {
  244. if (![[[NSUserDefaults standardUserDefaults] objectForKey:@"isShowNotice"] isEqualToString:@"doNotShowNotice"]) {
  245. [self initNoticeView];
  246. }
  247. }else{
  248. [self initNoticeView];
  249. }
  250. }
  251. - (void)initNoticeView
  252. {
  253. noticeView = [[UIView alloc] initWithFrame:kFrame];
  254. noticeView.backgroundColor = windowBlockColor;
  255. [[UIApplication sharedApplication].keyWindow addSubview:noticeView];
  256. NSString *noticeString = @"请注意:\n\n 本系统是按照2016驾驶员培训新国标要求,严格照规范设计,终端上传分钟学时来计算,在计时过程中请注意以下几点: \n\n1、如果所在地市有开启围栏,请注意确保您当前的位置在规定的围栏内训练,否则分钟学时无效 \n\n2、如果所在地市有开启培训时段,请确保您当前训练时间符合规定,比如早上6:00-20:00 \n\n3、确保教练手机是正常联网且安装支持3G以上的移动,联通和电信的SIM,否则无法采集到手机终端的位置,系统会判定分钟学时无效 \n\n4、系统为防止特殊情况,教练带教过程接到电话,允许断网一段时间,默认15分钟,如果超过15分钟,所带教学员的分钟学时无效 \n\n5、学员和教练的有效距离不能超过规定距离,否则分钟学时无效,详情请咨询教练或您所在的驾校 \n\n6、系统默认在2分钟及以上时间段内,如果移动距离为0米,视为无效分钟学时 \n\n7、根据规定,学员科目二和科目三1分钟内移动距离不能低于规定的数值,否则分钟学时无效,具体询问驾校或教练 \n\n8、如果您选择计时收费训练,您可以在训练结束且支付完成后对教练进行评价和投诉,如果训练完成后不支付,您的学时将无效且无法进行下一次训练 \n\n 为了保证您的合法利益,请遵守规定,同时也请提醒您的教练,手机不能断网或在带教过程中长时间接听电话,否则会影响您的学时有效性判断,导致学时无效";
  257. CGFloat noticeH = [noticeString heightForWid:kSize.width - 80 Font:Font17] + 10;
  258. UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(20, kNavOffSet, kSize.width - 40, kSize.height - kNavOffSet - 100 - kSafeAreaBottomHeight)];
  259. scrollView.contentSize = CGSizeMake(kSize.width - 40, noticeH + 50);
  260. scrollView.backgroundColor = backGroundColor;
  261. [noticeView addSubview:scrollView];
  262. [scrollView addViewWithRect:CGRectMake(20, scrollView.y + scrollView.height, scrollView.width, 1)];
  263. UILabel *noticeLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 20, kSize.width - 80, noticeH)];
  264. noticeLabel.numberOfLines = 0;
  265. [noticeLabel setText:noticeString Font:Font17 TextColor:kTitleColor];
  266. [scrollView addSubview:noticeLabel];
  267. UIView *btnView = [[UIView alloc] initWithFrame:CGRectMake(20, scrollView.y + scrollView.height + 1, scrollView.width, 40)];
  268. btnView.backgroundColor = backGroundColor;
  269. [noticeView addSubview:btnView];
  270. NSArray *titles = @[@"不再显示",@"不同意",@"同意"];
  271. CGFloat w = scrollView.width/4.0;
  272. for (int i = 0; i < 3; i ++) {
  273. UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
  274. if (i == 0) {
  275. btn.frame = CGRectMake(0, 0, 2*w, 40);
  276. }else{
  277. btn.frame = CGRectMake(w + i*w, 0, w, 40);
  278. }
  279. [btn setTitle:titles[i] textColor:kTitleColor Font:FontTitle fotState:UIControlStateNormal];
  280. [btn target:self tag:20 + i];
  281. [btnView addSubview:btn];
  282. if (i == 0) {
  283. isForeverBtn = btn;
  284. }
  285. }
  286. [isForeverBtn addViewWithRect:CGRectMake(2*w - 1, 0, 2, 40)];
  287. [isForeverBtn addViewWithRect:CGRectMake(3*w - 1, 0, 2, 40)];
  288. }
  289. -(UIView *)blueToothLabel {
  290. if (!_blueToothLabel) {
  291. _blueToothLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, (kSize.height - 90)/2.0, kSize.width - 60, 80)];
  292. _blueToothLabel.numberOfLines = 0;
  293. _blueToothLabel.backgroundColor = backGroundColor;
  294. [_blueToothLabel setBoardWid:5 Color:contentTextColor CornerRadius:6];
  295. [_blueToothLabel setText:@"" Font:24 TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  296. }
  297. return _blueToothLabel;
  298. }
  299. - (void)addBlueToothLabelWithContent:(NSString *)string {
  300. [[UIApplication sharedApplication].keyWindow addSubview:self.blueToothLabel];
  301. self.blueToothLabel.text = string;
  302. }
  303. - (void)removeBlueToothLabel {
  304. if (_blueToothLabel) {
  305. [_blueToothLabel removeFromSuperview];
  306. }
  307. }
  308. -(void)viewDidAppear:(BOOL)animated
  309. {
  310. [super viewDidAppear:animated];
  311. if (timer && peripheralName.length < 1) {
  312. [timer setFireDate:[NSDate distantPast]];
  313. [[UIApplication sharedApplication] setIdleTimerDisabled:peripheralName.length > 0?NO:YES];//屏幕常亮
  314. }
  315. if (locationManager) {
  316. [locationManager startUpdatingLocation];
  317. }else{
  318. [baiduLocationMan startUpdatingLocation];
  319. }
  320. //取消右滑「只针对拍照(present相机,再返回)有效,其它情况需走myuinavigation里限制」
  321. self.navigationController.interactivePopGestureRecognizer.enabled = NO;
  322. }
  323. -(void)viewDidDisappear:(BOOL)animated
  324. {
  325. [super viewDidDisappear:animated];
  326. if (signInTimer) {
  327. [signInTimer invalidate];
  328. signInTimer = nil;
  329. }
  330. if (peripheralName.length < 1) {
  331. if (locationManager) {
  332. [locationManager stopUpdatingLocation];
  333. }else{
  334. [baiduLocationMan stopUpdatingLocation];
  335. }
  336. }
  337. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];//关闭屏幕常亮
  338. }
  339. - (void)goBackByNavigation {
  340. [self setScreenBright];
  341. if (timer) {
  342. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"警告:退出当前页面将暂停实操计时,是否退出" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  343. if (selectedOtherButtonIndex == 0) {
  344. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];//关闭屏幕常亮
  345. timer.fireDate = [NSDate distantFuture];
  346. [self.view endEditing:1];
  347. [self.navigationController popViewControllerAnimated:YES];
  348. }
  349. }];
  350. }else{
  351. [self.view endEditing:1];
  352. [self.navigationController popViewControllerAnimated:YES];
  353. }
  354. }
  355. - (void)showAlertForBeginOrEndPeriodWithString:(NSString *)aString {
  356. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:aString alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  357. [self setScreenBright];
  358. if (selectedOtherButtonIndex == 0) {
  359. //调取相机扫描二维码
  360. ScanVC *scan = [[ScanVC alloc] init];
  361. scan.type = 1;
  362. [scan scanBlock:^(NSDictionary *dic) {
  363. scanDic = dic;
  364. _haveBlueTooth = NO;
  365. NSArray *dataArray = [dic[@"dataString"] componentsSeparatedByString:@";"];
  366. if (dataArray.count < 8) {//不开启蓝牙判断
  367. peripheralName = @"";
  368. [self startPeriod];
  369. }else {
  370. NSString *blueToothName = dataArray[6];
  371. if ([blueToothName isEqualToString:@"NONAME"]) {//不开启蓝牙判断
  372. peripheralName = @"";
  373. [self startPeriod];
  374. }else {//开启蓝牙判断
  375. _haveBlueTooth = YES;
  376. isNeedSignIn = YES;
  377. peripheralName = dataArray[6];
  378. [self searchBlueTooth];
  379. }
  380. }
  381. // NSLog(@"peripheralName----><>%@",peripheralName);
  382. }];
  383. [self navPushHideTabbarToVC:scan];
  384. }
  385. }];
  386. }
  387. - (void)btnClick:(UIButton *)sender {
  388. [self setScreenBright];
  389. if (sender.tag == 1) {
  390. //开始计时
  391. if (myCoordinate.latitude < 1) {
  392. ShowMsg(@"正在获取您的位置,请稍后再试!");
  393. return;
  394. }
  395. if (myDelegate.timer || isImitate) {
  396. ShowMsg(@"请先关闭其他计时");
  397. return;
  398. }
  399. if (isForceKeYi) {
  400. ShowMsg(@"当前账户正在进行集中理论学习,无法进行此操作");
  401. return;
  402. }
  403. if (isTerminal) {
  404. ShowMsg(@"当前账户正在终端实操计时,无法进行此操作");
  405. return;
  406. }
  407. [self showAlertForBeginOrEndPeriodWithString:@"请扫描教练手机二维码开始计时"];
  408. return;
  409. }
  410. if (sender.tag == 2) {
  411. //结束计时 查本地数据库有没有未上传的数据 有的话 全部上传 结束成功 更改按钮状态和tag
  412. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"请扫描教练手机二维码结束计时" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  413. if (selectedOtherButtonIndex == 0) {
  414. [self scanQrCode];
  415. }
  416. }];
  417. if (peripheralName.length == 0) {
  418. if ([gatherTrainDic.allKeys containsObject:@"comparisonPhoto"]) {
  419. NSArray *photoArray = gatherTrainDic[@"comparisonPhoto"];
  420. if ([photoArray isKindOfClass:[NSArray class]]) {
  421. NSString *method = @"comparisonPhoto";
  422. [jiaPeiManager requestAnythingWithURL:method array:photoArray data:nil completion:^(NSDictionary * root) {
  423. if (!root) {
  424. return ;
  425. }
  426. if ([root[@"code"] isEqualToString:@"0"]) {
  427. [gatherTrainDic removeObjectForKey:@"comparisonPhoto"];
  428. [self saveGatherTrainDic];
  429. }
  430. }];
  431. }
  432. }
  433. }
  434. return;
  435. }
  436. //结束失败 重新汇总学时
  437. if (sender.tag == 3) {
  438. minuteTrainArray = [DB_Helper quearySCTrainWithClassId:gatherTrainDic[@"classId"]];
  439. if (minuteTrainArray.count > 0) {
  440. //去上传未上传的学时 上传完调 uploadSignOutOrClassRecord
  441. [self uploadAppTrainPl];
  442. }else{
  443. [self uploadSignOutOrClassRecord];
  444. }
  445. if (peripheralName.length == 0) {
  446. if ([gatherTrainDic.allKeys containsObject:@"comparisonPhoto"]) {
  447. NSArray *photoArray = gatherTrainDic[@"comparisonPhoto"];
  448. if ([photoArray isKindOfClass:[NSArray class]]) {
  449. NSString *method = @"comparisonPhoto";
  450. [jiaPeiManager requestAnythingWithURL:method array:photoArray data:nil completion:^(NSDictionary * root) {
  451. if (!root) {
  452. return ;
  453. }
  454. if ([root[@"code"] isEqualToString:@"0"]) {
  455. [gatherTrainDic removeObjectForKey:@"comparisonPhoto"];
  456. [self saveGatherTrainDic];
  457. }
  458. }];
  459. }
  460. }
  461. }
  462. return;
  463. }
  464. //点击拍照 弹出提醒
  465. if (sender.tag == 7) {
  466. countDownBtn.selected = !countDownBtn.selected;
  467. if (countDownBtn.selected) {
  468. //弹出弹窗assign_btn
  469. countDownView = [[UIView alloc] initWithFrame:countDownBtn.frame];
  470. [countDownView setRound];
  471. [self.view addSubview:countDownView];
  472. UIImageView *imageView = [[UIImageView alloc] initWithFrame:countDownView.bounds];
  473. //拉伸图片
  474. UIImage * image = [UIImage imageNamed:@"assign_btn"];
  475. //计算左边端盖
  476. NSInteger leftCap = image.size.width * 0.5f;
  477. //计算顶部端盖
  478. NSInteger topCap = image.size.height * 0.5f;
  479. //拉伸imageView的大小 需要传入两个值 左端盖 和上端盖
  480. image = [image stretchableImageWithLeftCapWidth:leftCap topCapHeight:topCap];
  481. imageView.image = image;
  482. [countDownView addSubview:imageView];
  483. UILabel *label = [[UILabel alloc] initWithFrame:countDownView.bounds];
  484. label.backgroundColor = [UIColor clearColor];
  485. NSString * str = @"提示:拍照验证期间,实操计时将暂停直到完成拍照,退出拍照将结束计时";
  486. [label setText:str Font:Font17 TextColor:kTitleColor];
  487. label.numberOfLines = 0;
  488. [countDownView addSubview:label];
  489. [self.view bringSubviewToFront:countDownBtn];
  490. [UIView animateWithDuration:.3 animations:^{
  491. CGFloat labHeight = [str heightForWid:kSize.width - 110 -40 Font:Font17];
  492. countDownView.frame = CGRectMake(20, countDownBtn.y + countDownBtn.height - labHeight -20, kSize.width - 110, labHeight+20);
  493. imageView.frame = countDownView.bounds;
  494. label.frame = CGRectMake(20, 10, countDownView.bounds.size.width - 40, labHeight);
  495. } completion:nil];
  496. }else{
  497. //关闭弹窗
  498. [UIView animateWithDuration:.3 animations:^{
  499. countDownView.frame = countDownBtn.frame;
  500. } completion:^(BOOL finished) {
  501. [countDownView removeFromSuperview];
  502. }];
  503. }
  504. return;
  505. }
  506. if (sender.tag == 8) {//暂不支付 不评论
  507. [backView removeFromSuperview];
  508. return;
  509. }
  510. // if (sender.tag == 9) {//立即支付
  511. //
  512. // [backView removeFromSuperview];
  513. //
  514. // NSDictionary *dic = @{@"RO_START_TIME":finishDataDic[@"startTime"],
  515. // @"RO_END_TIME":finishDataDic[@"endTime"],
  516. // @"MINUTE":finishDataDic[@"validTime"],
  517. // @"RO_COACH_NAME":gatherTrainDic[@"coachName"],
  518. // @"PRICE":gatherTrainDic[@"price"],
  519. // @"RO_MONEY":finishDataDic[@"currentMoney"]};
  520. //
  521. // APViewController *ap = [[APViewController alloc] init];
  522. // ap.orderDic = dic;
  523. // [self navPushHideTabbarToVC:ap];
  524. //
  525. // return;
  526. // }
  527. if (sender.tag == 10) {//发起评价 计划订单评价 非计划学时评价
  528. [backView removeFromSuperview];
  529. NSMutableDictionary * dic = [NSMutableDictionary new];
  530. [dic setValue:gatherTrainDic[@"subject"] forKey:@"kmStr"];
  531. [dic setValue:gatherTrainDic[@"coachId"] forKey:@"coachId"];
  532. [dic setValue:gatherTrainDic[@"classId"] forKey:@"classId"];
  533. [dic setValue:gatherTrainDic[@"coachName"] forKey:@"coachName"];
  534. Evaluation * evVC = [[Evaluation alloc]init];
  535. if ([gatherTrainDic[@"isPlan"] isEqualToString:@"1"]) {
  536. //计划
  537. evVC.orderDic = dic;
  538. }else{//非计划
  539. evVC.xsDic = dic;
  540. }
  541. [self navPushHideTabbarToVC:evVC];
  542. return;
  543. }
  544. if (sender.tag == 20) {//是否还要显示
  545. sender.selected = !sender.selected;
  546. if (sender.selected) {
  547. sender.backgroundColor = RQ_MAIN_COLOR;
  548. }else{
  549. sender.backgroundColor = [UIColor clearColor];
  550. }
  551. }
  552. if (sender.tag == 21) {
  553. [noticeView removeFromSuperview];
  554. [self.view endEditing:1];
  555. [self.navigationController popViewControllerAnimated:YES];
  556. }
  557. if (sender.tag == 22) {
  558. if (isForeverBtn.selected) {
  559. //不在显示 本地存个字段
  560. [[NSUserDefaults standardUserDefaults] setValue:@"doNotShowNotice" forKey:@"isShowNotice"];
  561. }
  562. [noticeView removeFromSuperview];
  563. }
  564. }
  565. -(void)switchAction:(id)sender
  566. {
  567. [self setScreenBright];
  568. UISwitch *switchButton = (UISwitch*)sender;
  569. BOOL isButtonOn = [switchButton isOn];
  570. if (isButtonOn) {
  571. //showSwitchValue.text = @"是";
  572. isVoice = YES;
  573. }else {
  574. isVoice = NO;
  575. }
  576. }
  577. - (void)isUploadLocation
  578. {
  579. on_offBtn.hidden = NO;
  580. [self getGatherTrainDic];
  581. if ([gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  582. if ([gatherTrainDic[@"isOver"] isEqualToString:@"0"]) {
  583. //表明之前的计时没有结束。恢复计时吧
  584. //蓝牙
  585. peripheralName = gatherTrainDic[@"blueName"];
  586. if (peripheralName.length > 0) {
  587. //如果之前有蓝牙 现在也要重新开启起来
  588. self.haveBlueTooth = YES;
  589. [self searchBlueTooth];
  590. [self goToBackgroundTask];
  591. }
  592. minuteTrainDic = [NSMutableDictionary dictionary];
  593. [minuteTrainDic setValue:gatherTrainDic[@"classId"] forKey:@"classId"];
  594. [minuteTrainDic setValue:gatherTrainDic[@"classCode"] forKey:@"classCode"];
  595. [minuteTrainDic setValue:gatherTrainDic[@"trainNum"] forKey:@"trainNum"];
  596. [minuteTrainDic setValue:@"0.0000" forKey:@"obdMileage"];
  597. [minuteTrainDic setValue:@"0" forKey:@"obdRotationSpeed"];
  598. trainNum = gatherTrainDic[@"trainNum"];
  599. gpsArray = [NSMutableArray array];
  600. seconds = [gatherTrainDic[@"allTime"] integerValue];
  601. photoTime = [gatherTrainDic[@"photoTime"] integerValue];
  602. timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
  603. trainView.hidden = NO;
  604. myDelegate.timer = timer;
  605. [on_offBtn setTitle:@"结束计时" forState:UIControlStateNormal];
  606. on_offBtn.tag = 2;
  607. myDelegate.scPeriodVC = self;
  608. [[UIApplication sharedApplication] setIdleTimerDisabled:peripheralName.length > 0?NO:YES];//屏幕常亮
  609. [Tools playAudioWithString:@"断线虫连成功,已恢复计时"];
  610. [self reloadDetailLab];
  611. }
  612. if ([gatherTrainDic[@"isOver"] isEqualToString:@"2"]) {
  613. //表明之前的计时结束 但是上传失败
  614. peripheralName = gatherTrainDic[@"blueName"];
  615. [self reloadDetailLab];
  616. minuteTrainDic = [NSMutableDictionary dictionary];
  617. seconds = [gatherTrainDic[@"allTime"] integerValue];
  618. int hour = (int)seconds / 3600;
  619. int min = (int)seconds % 3600 / 60;
  620. int second = (int)seconds % 3600 % 60;
  621. NSString *min_s;
  622. NSString *second_s;
  623. if (min<10) {
  624. min_s=[NSString stringWithFormat:@"0%d",min];
  625. }else{
  626. min_s=[NSString stringWithFormat:@"%d",min];
  627. }
  628. if (second<10) {
  629. second_s=[NSString stringWithFormat:@"0%d",second];
  630. }else{
  631. second_s=[NSString stringWithFormat:@"%d",second];
  632. }
  633. timeLabel.text = [NSString stringWithFormat:@"0%d:%@:%@",hour,min_s,second_s];
  634. [on_offBtn setTitle:@"汇总学时" forState:UIControlStateNormal];
  635. on_offBtn.tag = 3;
  636. }
  637. }
  638. }
  639. #pragma mark 蓝牙连接通过 去签到计时
  640. - (void)startPeriod {
  641. //@"scanType":@"scPeriod",@"dataString":@""
  642. if ([scanDic[@"scanType"] isEqualToString:@"scPeriod"]) {
  643. //非计划实操计时
  644. isPlanPeriod = NO;
  645. coachdataArray = [scanDic[@"dataString"] componentsSeparatedByString:@";"];
  646. if (coachdataArray.count < 6) {
  647. ShowMsg(@"教练信息获取失败!请重试");
  648. return;
  649. }
  650. // 教练outID 教练姓名 价格 科目 电话号码 终端设备号 蓝牙名称 有效时间
  651. gatherTrainDic = [NSMutableDictionary dictionary];
  652. [gatherTrainDic setValue:coachdataArray[0] forKey:@"coachId"];
  653. [gatherTrainDic setValue:coachdataArray[1] forKey:@"coachName"];
  654. [gatherTrainDic setValue:coachdataArray[2] forKey:@"price"];
  655. [gatherTrainDic setValue:coachdataArray[3] forKey:@"subject"];
  656. [gatherTrainDic setValue:coachdataArray[4] forKey:@"coachSim"];
  657. [gatherTrainDic setValue:coachdataArray[5] forKey:@"deviceNum"];
  658. [gatherTrainDic setValue:peripheralName forKey:@"blueName"];
  659. //生成各种编码 签到 生成定时器 改变按钮状态 然后上传分钟学时 然后做断网处理
  660. [self getClassIdAndSoOn];
  661. [self uploadStuSign];
  662. }else if ([scanDic[@"scanType"] isEqualToString:@"jhPeriod"]){
  663. //计划实操计时
  664. isPlanPeriod = YES;
  665. //参数分别是 教练outID 教练姓名 学生ID 预约ID 电话号码 终端设备号 蓝牙名称 有效时间
  666. coachdataArray = [scanDic[@"dataString"] componentsSeparatedByString:@";"];
  667. if (coachdataArray.count < 6) {
  668. ShowMsg(@"教练信息获取失败!请重试");
  669. return;
  670. }
  671. //计划的要先生成各种ID 需要用到deviceNum这个参数
  672. gatherTrainDic = [NSMutableDictionary dictionary];
  673. [gatherTrainDic setValue:coachdataArray[0] forKey:@"coachId"];
  674. [gatherTrainDic setValue:coachdataArray[1] forKey:@"coachName"];
  675. [gatherTrainDic setValue:coachdataArray[2] forKey:@"studentId"];
  676. [gatherTrainDic setValue:coachdataArray[3] forKey:@"reserveId"];
  677. [gatherTrainDic setValue:coachdataArray[4] forKey:@"coachSim"];
  678. [gatherTrainDic setValue:coachdataArray[5] forKey:@"deviceNum"];
  679. [gatherTrainDic setValue:peripheralName forKey:@"blueName"];
  680. [self getClassIdAndSoOn];
  681. //生成订单
  682. [self uploadReserveOrder];
  683. }else if ([scanDic[@"scanType"] isEqualToString:@"allSignOut"]) {
  684. //先关闭定时器
  685. [timer invalidate];
  686. timer = nil;
  687. myDelegate.timer = nil;
  688. myDelegate.scPeriodVC = nil;
  689. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];//关闭屏幕常亮
  690. on_offBtn.tag = 3;//表明点了结束计时 但没结束成功的情况
  691. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  692. [self saveGatherTrainDic];
  693. minuteTrainArray = [DB_Helper quearySCTrainWithClassId:gatherTrainDic[@"classId"]];
  694. if (minuteTrainArray.count > 0) {
  695. [self uploadAppTrainPl];
  696. }else{
  697. [self uploadSignOutOrClassRecord];
  698. }
  699. }
  700. }
  701. #pragma mark gps定位相关
  702. //断网情况开启gps定位
  703. -(void)setGPSLocationService{
  704. //实例化manager
  705. locationManager=[[CLLocationManager alloc]init];
  706. //设置代理
  707. locationManager.delegate=self;
  708. //设置定位精度
  709. //定位要求的精度越高、属性distanceFilter的值越小,应用程序的耗电量就越大。
  710. locationManager.desiredAccuracy=kCLLocationAccuracyBest;
  711. //定位距离
  712. locationManager.distanceFilter=kCLDistanceFilterNone;//一起燃烧
  713. //申请定位许可,iOS8以后特有
  714. /** 由于IOS8中定位的授权机制改变 需要进行手动授权
  715. * 获取授权认证,两个方法:
  716. * [self.locationManager requestWhenInUseAuthorization];
  717. * [self.locationManager requestAlwaysAuthorization];
  718. */
  719. if([locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
  720. [locationManager requestAlwaysAuthorization];
  721. }
  722. //开始定位
  723. [locationManager startUpdatingLocation];
  724. }
  725. - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations {
  726. CLLocation *loctaion = [locations firstObject];
  727. //打印出经度和纬度
  728. CLLocationCoordinate2D coordinate = loctaion.coordinate;
  729. //解密加密后的坐标字典
  730. CLLocationCoordinate2D baiduCoor = BMKCoordTrans(coordinate, BMK_COORDTYPE_GPS, BMK_COORDTYPE_BD09LL);//转换GPS坐标至百度坐标(加密后的坐标)
  731. myCoordinate = baiduCoor;
  732. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  733. dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  734. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  735. NSString *strDate = [dateFormatter stringFromDate:loctaion.timestamp];
  736. NSString *courseString = [NSString stringWithFormat:@"%.0f",loctaion.course];
  737. if ([courseString containsString:@"-"]) {
  738. courseString = [[courseString componentsSeparatedByString:@"-"] lastObject];
  739. if ([courseString containsString:@"."]) {
  740. courseString = [[courseString componentsSeparatedByString:@"."] firstObject];
  741. }
  742. }
  743. gpsDic = [NSMutableDictionary dictionaryWithDictionary:@{
  744. @"latitude":[NSString stringWithFormat:@"%f",baiduCoor.latitude],
  745. @"longitude":[NSString stringWithFormat:@"%f",baiduCoor.longitude],
  746. @"altitude":[NSString stringWithFormat:@"%.2f",loctaion.altitude],
  747. @"course":courseString,
  748. @"timestamp":strDate,
  749. @"speed":[NSString stringWithFormat:@"%.4f",loctaion.speed*3.6 > 0.0000 ? loctaion.speed*3.6 : 0.0000]
  750. }];
  751. if (loctaion.speed*3.6 > systemMaxSpeed) {
  752. [Tools playAudioWithString:[NSString stringWithFormat:@"当前车速为%.1f,您已超速,请注意控制车速",[gpsDic[@"speed"] floatValue]]];
  753. }
  754. //距离累加
  755. // if (lastGPSDic) {
  756. // mileageFloat += [self getDistance];
  757. // }
  758. //
  759. // lastGPSDic = gpsDic;
  760. // NSLog(@"系统定位--\n经度(对应百度坐标系):%f \n纬度(对应百度坐标系):%f \n海拔:%f \n方向(<0无效):%f \n时间:%@ \n速度(<0无效): %f",
  761. // baiduCoor.latitude,//经度Stringlon
  762. // baiduCoor.longitude,//纬度Stringlat
  763. // newLocation.altitude,//海拔Integerelevation
  764. // newLocation.course,//方向Integerdirection
  765. // strDate,//信息时间StringreceiveTimeGPS
  766. // newLocation.speed/3.6//卫星定位速度速度doublelocationSpeed
  767. // );
  768. }
  769. #pragma mark 百度地图
  770. /**
  771. * @brief 当定位发生错误时,会调用代理的此方法。
  772. * @param manager 定位 BMKLocationManager 类。
  773. * @param error 返回的错误,参考 CLError 。
  774. */
  775. - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nullable)error{
  776. ShowMsg([NSString stringWithFormat:@"获取位置错误:%@",error.description]);
  777. }
  778. /**
  779. * @brief 连续定位回调函数。
  780. * @param manager 定位 BMKLocationManager 类。
  781. * @param location 定位结果,参考BMKLocation。
  782. * @param error 错误信息。
  783. */
  784. - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error{
  785. if (location)
  786. {
  787. myCoordinate = location.location.coordinate;
  788. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  789. dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  790. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  791. NSString *strDate = [dateFormatter stringFromDate:location.location.timestamp];
  792. CLLocationCoordinate2D baiduCoor = location.location.coordinate;
  793. NSString *courseString = [NSString stringWithFormat:@"%.0f",location.location.course];
  794. if ([courseString containsString:@"-"]) {
  795. courseString = [[courseString componentsSeparatedByString:@"-"] lastObject];
  796. if ([courseString containsString:@"."]) {
  797. courseString = [[courseString componentsSeparatedByString:@"."] firstObject];
  798. }
  799. }
  800. gpsDic = [NSMutableDictionary dictionaryWithDictionary:@{
  801. @"latitude":[NSString stringWithFormat:@"%f",baiduCoor.latitude],
  802. @"longitude":[NSString stringWithFormat:@"%f",baiduCoor.longitude],
  803. @"altitude":[NSString stringWithFormat:@"%.2f",location.location.altitude],
  804. @"course":courseString? : @"",
  805. @"timestamp":strDate? : @"",
  806. @"speed":[NSString stringWithFormat:@"%.4f",location.location.speed*3.6 > 0.0000 ? location.location.speed*3.6 : 0.0000]
  807. }];
  808. if (location.location.speed*3.6 > systemMaxSpeed) {
  809. [Tools playAudioWithString:[NSString stringWithFormat:@"当前车速为%.1f,您已超速,请注意控制车速",[gpsDic[@"speed"] floatValue]]];
  810. }
  811. //距离累加
  812. // if (lastGPSDic) {
  813. // mileageFloat += [self getDistance];
  814. // }
  815. //
  816. // lastGPSDic = gpsDic;
  817. // NSLog(@"BMKdidUpdateUserLocation \nlat %f,\nlong %f \n海拔 %f \n方向(<0无效):%f \n时间:%@ \n速度(<0无效): %f",
  818. // userLocation.location.coordinate.latitude,//经度Stringlon
  819. // userLocation.location.coordinate.longitude,//纬度Stringlat
  820. // userLocation.location.altitude,//海拔Integerelevation
  821. // userLocation.location.course,//方向Integerdirection
  822. // strDate,//信息时间StringreceiveTimeGPS
  823. // userLocation.location.speed*60*60/1000//卫星定位速度速度doublelocationSpeed
  824. // );
  825. }
  826. }
  827. -(CGFloat)getDistance
  828. {
  829. CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:[gpsDic[@"latitude"] floatValue] longitude:[gpsDic[@"longitude"] floatValue]];
  830. CLLocation *lastLocation = [[CLLocation alloc] initWithLatitude:[lastGPSDic[@"latitude"] floatValue] longitude:[lastGPSDic[@"longitude"] floatValue]];
  831. CLLocationDistance kilometers=[newLocation distanceFromLocation:lastLocation]/1000;
  832. return kilometers;
  833. }
  834. #pragma mark 拍照
  835. - (void)takePhoto
  836. {
  837. if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]){
  838. //创建pickerVC
  839. AllLightImagePickerController * pickerVC=[[AllLightImagePickerController alloc]init];
  840. //设置图片来源类型:可以是相机/相册
  841. /*UIImagePickerControllerSourceTypePhotoLibrary;相册
  842. UIImagePickerControllerSourceTypeCamera;相机
  843. */
  844. pickerVC.sourceType=UIImagePickerControllerSourceTypeCamera;
  845. //是否可编辑。
  846. //pickerVC.allowsEditing=NO;
  847. //设置代理
  848. pickerVC.delegate=self;
  849. //前置摄像头
  850. pickerVC.cameraDevice = UIImagePickerControllerCameraDeviceFront;
  851. //拍照模式
  852. pickerVC.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
  853. //弹出pickerVC
  854. [self presentViewController:pickerVC animated:YES completion:^{
  855. nil;
  856. //只要这个pickerVC没有释放你的屏幕常亮都自动设:no
  857. }];
  858. //ShowMsg(@"三秒后自动拍照");
  859. [Tools playAudioWithString:@"三秒后自动拍照"];
  860. //延迟三秒自动拍照
  861. [pickerVC performSelector:@selector(takePicture) withObject:nil afterDelay:4];
  862. }else{
  863. //打开相机失败 特殊情况比如相机硬件损坏 这里无法解决
  864. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"相机打开失败,请在“设置-极速驾培”中打开相机权限,否则将结束计时" preferredStyle:UIAlertControllerStyleAlert];
  865. [alert addAction:[UIAlertAction actionWithTitle:@"打开相机" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  866. [self takePhoto];
  867. }]];
  868. [alert addAction:[UIAlertAction actionWithTitle:@"结束计时" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  869. //结束计时
  870. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"拍照失败,请扫描教练手机二维码结束计时" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  871. [self scanQrCode];
  872. }];
  873. }]];
  874. [self presentViewController:alert animated:true completion:nil];
  875. }
  876. }
  877. -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{
  878. [picker dismissViewControllerAnimated:YES completion:^{
  879. if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@"public.image"])
  880. {
  881. photoTime = 0;
  882. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  883. [self saveGatherTrainDic];
  884. //如果前面的allowediting设置为No的话,这里直接用originalImage好了
  885. UIImage * image = info[UIImagePickerControllerEditedImage];
  886. if (!image) {
  887. image = info[UIImagePickerControllerOriginalImage];
  888. }
  889. //上传照片 开启定时
  890. [timer setFireDate:[NSDate distantPast]];
  891. [self upLoadPhotoWithImage:image];
  892. }
  893. }];
  894. }
  895. - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
  896. {
  897. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"警告:取消拍照将结束本次实操计时," preferredStyle:UIAlertControllerStyleAlert];
  898. [alert addAction:[UIAlertAction actionWithTitle:@"返回" style:UIAlertActionStyleCancel handler:nil]];
  899. [alert addAction:[UIAlertAction actionWithTitle:@"结束计时" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
  900. [picker dismissViewControllerAnimated:YES completion:^{
  901. //结束计时
  902. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"拍照失败,请扫描教练手机二维码结束计时" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  903. [self scanQrCode];
  904. }];
  905. }];
  906. }]];
  907. [picker presentViewController:alert animated:true completion:nil];
  908. }
  909. #pragma mark tableview
  910. -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  911. {
  912. return dataSourceArray.count;
  913. }
  914. -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  915. {
  916. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
  917. if (cell == nil) {
  918. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
  919. cell.selectionStyle = UITableViewCellSelectionStyleNone;
  920. }
  921. [cell.textLabel setText:[dataSourceArray[dataSourceArray.count - indexPath.row - 1] substringFromIndex:1] Font:Font17 TextColor:[[dataSourceArray[dataSourceArray.count - indexPath.row - 1] substringToIndex:1] isEqualToString:@"1"]?[UIColor redColor]:[UIColor blackColor]];
  922. [cell.textLabel setNumberOfLines:0];
  923. return cell;
  924. }
  925. #pragma mark 屏幕变暗相关
  926. -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
  927. [super touchesBegan:touches withEvent:event];
  928. [self setScreenBright];
  929. }
  930. -(void)setScreenBright{
  931. _scrBrtTime = SCReenBRIGHTTIME;//有交互就要重新设置时间
  932. //如果是代码修改的屏幕亮度,并且记录值大于当前屏幕亮度
  933. if (_flag == YES && _scrStartBright > [[UIScreen mainScreen] brightness]) {
  934. [[UIScreen mainScreen] setBrightness: _scrStartBright];
  935. }
  936. }
  937. #pragma mark 教学信息更新
  938. -(void)reloadDetailLab{
  939. int i=0;
  940. for (UILabel * detailLab in detailLabArr) {
  941. if (i == 0) {
  942. detailLab.text = [NSString stringWithFormat:@"教练:%@",gatherTrainDic[@"coachName"]];
  943. }else if (i == 1){
  944. detailLab.text = [NSString stringWithFormat:@"科目:科%@",[gatherTrainDic[@"subject"] isEqualToString:@"2"]?@"二":@"三"];
  945. }else{
  946. if ([gatherTrainDic[@"price"] isEqualToString:@"免费"]) {
  947. detailLab.text = [NSString stringWithFormat:@"单价:%@",gatherTrainDic[@"price"]];
  948. }else{
  949. detailLab.text = [NSString stringWithFormat:@"单价:%@元",gatherTrainDic[@"price"]];
  950. }
  951. }
  952. i++;
  953. }
  954. // [self refreshTrainViewLables];
  955. }
  956. //-(void)refreshTrainViewLables{
  957. // NSArray *values = [gatherTrainDic valueForKey:@"timesValue"];
  958. // int i=0;
  959. // for (UILabel *lab in trainViewLabs) {
  960. // lab.text = values[i++];
  961. // }
  962. //}
  963. #pragma mark 数据请求
  964. //学员签到
  965. - (void)uploadStuSign
  966. {
  967. [LoadingView showHUD];
  968. if (![Util connectedToNetWork]) {
  969. showMsgUnconnect();
  970. [self closeBlueTooth];
  971. return;
  972. }
  973. //dataString: 教练outID 教练姓名 价格 科目 教练手机 终端编号 有效时间
  974. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  975. dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  976. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  977. NSString *timeString = [dateFormatter stringFromDate:[NSDate date]];
  978. NSMutableArray *arr=[NSMutableArray array];
  979. [arr addPro:@"userId" Value:RQ_USER_MANAGER.currentUser._id];
  980. [arr addPro:@"stuId" Value:RQ_USER_MANAGER.currentUser.outId];
  981. [arr addPro:@"subject" Value:gatherTrainDic[@"subject"]];
  982. [arr addPro:@"classId" Value:classId];
  983. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  984. [arr addPro:@"coachId" Value:[coachdataArray firstObject]];
  985. [arr addPro:@"sim" Value:RQ_USER_MANAGER.currentUser.telphone];
  986. [arr addPro:@"gps" Value:[NSString stringWithFormat:@"%f,%f,%@,3",myCoordinate.longitude,myCoordinate.latitude,timeString]];
  987. NSString* method = @"uploadStuSign";
  988. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  989. RemoveHUD();
  990. // NSDictionary * dic = root[@"body"];
  991. //NSArray * values = @[dic[@"CURRENTTIME"],dic[@"TOTALTIME"],dic[@"NEEDTIME"]];
  992. //存本地
  993. //[gatherTrainDic setValue:values forKey:@"timesValue"];
  994. // [self saveGatherTrainDic];
  995. if (!root) {
  996. ShowMsg(@"签到失败!");
  997. [Tools playAudioWithString:@"学员签到失败,请重试"];
  998. if (isPlanPeriod) {
  999. [self delReserveOrder];
  1000. }
  1001. [self closeBlueTooth];
  1002. gatherTrainDic = nil;
  1003. [self saveGatherTrainDic];
  1004. return ;
  1005. }
  1006. if ([root[@"code"] isEqualToString:@"1"]) {
  1007. ShowMsg(root[@"body"]);
  1008. [Tools playAudioWithString:root[@"body"]];
  1009. if (isPlanPeriod) {
  1010. [self delReserveOrder];
  1011. }
  1012. [self closeBlueTooth];
  1013. return;
  1014. }
  1015. if (peripheralName.length > 0 && [gatherTrainDic[@"subject"] integerValue] == 2) {
  1016. //OBD科二签到 要先拍照验证
  1017. [Tools playAudioWithString:@"签到成功,请面向摄像头进行人脸验证"];
  1018. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"签到成功,点击“确认”按钮开始拍照,请面向摄像头" preferredStyle:UIAlertControllerStyleAlert];
  1019. [alert addAction:[UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  1020. isSubjectTwoSignIn = YES;
  1021. [self performSelector:@selector(takePhotoByBlueTooth) withObject:nil afterDelay:3];
  1022. signInTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(signInTimerRun) userInfo:nil repeats:YES];
  1023. }]];
  1024. [self presentViewController:alert animated:NO completion:nil];
  1025. }else {
  1026. ShowMsg(@"签到成功!");
  1027. [Tools playAudioWithString:@"签到成功,开始实操计时,请系好安全带"];
  1028. isSubjectTwoSignIn = NO;
  1029. [self beginTimer];
  1030. }
  1031. }];
  1032. }
  1033. - (void)beginTimer {
  1034. //将之前的学时全部清空
  1035. [DB_Helper deleteAllSCTrain];
  1036. //刷新学时显示
  1037. [self reloadDetailLab];
  1038. [gatherTrainDic setValue:classId forKey:@"classId"];
  1039. [gatherTrainDic setValue:classCode forKey:@"classCode"];
  1040. [gatherTrainDic setValue:trainNum forKey:@"trainNum"];
  1041. [gatherTrainDic setValue:@"0" forKey:@"allPrice"];
  1042. [gatherTrainDic setValue:@"0.0000" forKey:@"allMileage"];
  1043. [gatherTrainDic setValue:@"0.0000" forKey:@"obdMileage"];
  1044. [gatherTrainDic setValue:@"0" forKey:@"allTime"];//秒
  1045. [gatherTrainDic setValue:isPlanPeriod == YES?@"1":@"2" forKey:@"isPlan"];
  1046. [gatherTrainDic setValue:@"0" forKey:@"isOver"];
  1047. //classId , classCode , trainNum , maxSpeed , mileage , gps , obdMileage , obdRotationSpeed
  1048. minuteTrainDic = [NSMutableDictionary dictionary];
  1049. [minuteTrainDic setValue:classId forKey:@"classId"];
  1050. [minuteTrainDic setValue:classCode forKey:@"classCode"];
  1051. [minuteTrainDic setValue:trainNum forKey:@"trainNum"];
  1052. [minuteTrainDic setValue:@"0.0000" forKey:@"obdMileage"];
  1053. [minuteTrainDic setValue:@"0" forKey:@"obdRotationSpeed"];
  1054. [self saveGatherTrainDic];//保存至本地 可以用于断线重连
  1055. gpsArray = [NSMutableArray array];
  1056. mileageFloat = 0.0000;
  1057. seconds = 0;
  1058. disconnectSeconds = 0;
  1059. photoTime = 0;
  1060. timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerRun) userInfo:nil repeats:YES];
  1061. trainView.hidden = NO;
  1062. myDelegate.timer = timer;
  1063. myDelegate.scPeriodVC = self;
  1064. [[UIApplication sharedApplication] setIdleTimerDisabled:peripheralName.length > 0?NO:YES];//屏幕常亮
  1065. if (peripheralName.length > 0) {
  1066. [self goToBackgroundTask];
  1067. }
  1068. [on_offBtn setTitle:@"结束计时" forState:UIControlStateNormal];
  1069. on_offBtn.tag = 2;
  1070. }
  1071. - (void)saveGatherTrainDic
  1072. {
  1073. NSString *filePath = [Tools getPathWithFileName:@"gatherTrainDic.plist"];
  1074. [gatherTrainDic writeToFile:filePath atomically:YES];
  1075. }
  1076. - (void)getGatherTrainDic
  1077. {
  1078. NSString *filePath = [Tools getPathWithFileName:@"gatherTrainDic.plist"];
  1079. if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
  1080. gatherTrainDic = [NSMutableDictionary dictionaryWithContentsOfFile:filePath];
  1081. }
  1082. }
  1083. - (void)getClassIdAndSoOn
  1084. {
  1085. //classId
  1086. NSTimeInterval timeInterval = [[NSDate date] timeIntervalSince1970]*1000;
  1087. NSString *timeString = [[[[NSString stringWithFormat:@"%f",timeInterval] substringFromIndex:1] componentsSeparatedByString:@"."] firstObject];
  1088. NSInteger redomNum = arc4random()%8999 + 1000;
  1089. //NSInteger time = [[timeString substringToIndex:7] integerValue] - redomNum;
  1090. //classId = [NSString stringWithFormat:@"%d%@",(int)time,[timeString substringFromIndex:7]];
  1091. classId = [NSString stringWithFormat:@"%d%@",(int)redomNum,timeString];
  1092. //课程编码
  1093. NSString *carTypeString = @"21";
  1094. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"A1"]) {
  1095. carTypeString = @"01";
  1096. }
  1097. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"A2"]) {
  1098. carTypeString = @"02";
  1099. }
  1100. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"A3"]) {
  1101. carTypeString = @"03";
  1102. }
  1103. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"B1"]) {
  1104. carTypeString = @"11";
  1105. }
  1106. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"B2"]) {
  1107. carTypeString = @"12";
  1108. }
  1109. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"C1"]) {
  1110. carTypeString = @"21";
  1111. }
  1112. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"C2"]) {
  1113. carTypeString = @"22";
  1114. }
  1115. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"C3"]) {
  1116. carTypeString = @"23";
  1117. }
  1118. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"C4"]) {
  1119. carTypeString = @"24";
  1120. }
  1121. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"C5"]) {
  1122. carTypeString = @"25";
  1123. }
  1124. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"D"]) {
  1125. carTypeString = @"31";
  1126. }
  1127. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"E"]) {
  1128. carTypeString = @"32";
  1129. }
  1130. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"F"]) {
  1131. carTypeString = @"33";
  1132. }
  1133. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"M"]) {
  1134. carTypeString = @"41";
  1135. }
  1136. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"N"]) {
  1137. carTypeString = @"42";
  1138. }
  1139. if ([RQ_USER_MANAGER.currentUser.carType isEqualToString:@"P"]) {
  1140. carTypeString = @"43";
  1141. }
  1142. classCode = [NSString stringWithFormat:@"1%@%@120000",carTypeString,coachdataArray[3]];
  1143. //学时编号
  1144. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1145. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1146. [formatter setDateFormat:@"yyMMdd"];
  1147. NSString *dateString = [formatter stringFromDate:[NSDate date]];
  1148. NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  1149. trainOrderNum = [userDefaults valueForKey:@"trainOrderNum"]; //17-02-09,20
  1150. //![trainOrderNum isKindOfClass:[NSString class]]
  1151. if (trainOrderNum == nil || ![[[trainOrderNum componentsSeparatedByString:@","] firstObject] isEqualToString:dateString]) {
  1152. [userDefaults setValue:[NSString stringWithFormat:@"%@,0",dateString] forKey:@"trainOrderNum"];
  1153. }
  1154. trainOrderNum = [userDefaults valueForKey:@"trainOrderNum"];
  1155. NSString *trainString = @"";
  1156. int trainInt = [[[trainOrderNum componentsSeparatedByString:@","] lastObject] intValue];
  1157. if (trainInt < 10) {
  1158. trainString = [NSString stringWithFormat:@"000%d",trainInt];
  1159. }else if (trainInt < 100){
  1160. trainString = [NSString stringWithFormat:@"00%d",trainInt];
  1161. }else if (trainInt < 1000){
  1162. trainString = [NSString stringWithFormat:@"0%d",trainInt];
  1163. }else{
  1164. trainString = [NSString stringWithFormat:@"%d",trainInt];
  1165. }
  1166. trainNum = [NSString stringWithFormat:@"%@%@%@",RQ_USER_MANAGER.currentUser.stuDevNum,dateString,trainString];
  1167. }
  1168. - (void)signInTimerRun {
  1169. if (isConnectBlueTooth) {
  1170. //验证蓝牙拍照是否响应
  1171. if ([blueToothOrder containsString:@"AA2F"]) {
  1172. if ([blueToothOrder isEqualToString:@"AA2FWAIT"]) {
  1173. //代表拍照成功 但是没有比对完成
  1174. return;
  1175. }
  1176. bTRequestTime ++;
  1177. //蓝牙没响应 重新发送命令 并且重发计时+1
  1178. if (bTRequestTime > 5) {
  1179. bTRequestTime = 0;
  1180. reOrderCount ++;
  1181. if (reOrderCount < 3) {
  1182. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:blueToothOrder]];
  1183. }else {
  1184. reOrderCount = 0;
  1185. [self removeBlueToothLabel];
  1186. [Tools playAudioWithString:@"拍照失败!"];
  1187. [self showAlertTakePhotoFail];
  1188. }
  1189. }
  1190. }
  1191. }
  1192. }
  1193. - (void)timerRun
  1194. {
  1195. if (!isConnectBlueTooth && peripheralName.length > 0) {//计时过程中蓝牙断开连接
  1196. disconnectSeconds ++;
  1197. if (disconnectSeconds%5 == 0) {
  1198. if (_cbcManager && self.peripheral) {
  1199. [_cbcManager connectPeripheral:self.peripheral options:nil];
  1200. }
  1201. }
  1202. return;
  1203. }
  1204. if (isConnectBlueTooth) {
  1205. //心跳包验证 如果没有心跳包交互 就关闭计时
  1206. if (![blueToothOrder containsString:@"AA2F"]) {
  1207. heartSeconds ++;
  1208. if (heartSeconds > 180) {//该蓝牙没有发送心跳包验证 视为非法蓝牙
  1209. [Tools playAudioWithString:@"当前蓝牙连接为非法连接,系统将结束计时"];
  1210. if (heartSeconds > 183) {
  1211. //先关闭定时器
  1212. [timer invalidate];
  1213. timer = nil;
  1214. myDelegate.timer = nil;
  1215. //关闭蓝牙连接
  1216. [self closeBlueTooth];
  1217. on_offBtn.tag = 3;//表明点了结束计时 但没结束成功的情况
  1218. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  1219. [self saveGatherTrainDic];
  1220. minuteTrainArray = [DB_Helper quearySCTrainWithClassId:gatherTrainDic[@"classId"]];
  1221. if (minuteTrainArray.count > 0) {
  1222. [self uploadAppTrainPl];
  1223. }else{
  1224. [self uploadSignOutOrClassRecord];
  1225. }
  1226. }
  1227. return;
  1228. }
  1229. }
  1230. //验证蓝牙拍照是否响应
  1231. if ([blueToothOrder containsString:@"AA2F"]) {
  1232. if ([blueToothOrder isEqualToString:@"AA2FWAIT"]) {
  1233. //代表拍照成功 但是没有比对完成
  1234. return;
  1235. }
  1236. bTRequestTime ++;
  1237. //蓝牙没响应 重新发送命令 并且重发计时+1
  1238. if (bTRequestTime > 4) {
  1239. bTRequestTime = 0;
  1240. reOrderCount ++;
  1241. if (reOrderCount < 3) {
  1242. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:blueToothOrder]];
  1243. }else {
  1244. reOrderCount = 0;
  1245. [self removeBlueToothLabel];
  1246. blueToothOrder = @"";
  1247. //失败次数超过3 重新拍照 或初始化拍照模块
  1248. if ([blueToothOrder isEqualToString:@"AA2F03040509"]) {//不能响应拍照命令 执行初始化 初始化完 继续拍照
  1249. //danson 这里不做初始化摄像头的操作了 这里直接恢复计时好了
  1250. //[Tools playAudioWithString:@"摄像头拍照失败,请报修"];
  1251. if (seconds > photoTime) {
  1252. int num = (int)(seconds - photoTime)/60 + 10;
  1253. photoTime += 60 * num;
  1254. }
  1255. }else {//获取数据失败 更改拍照时间 过一会继续尝试拍照
  1256. if (seconds > photoTime) {
  1257. int num = (int)(seconds - photoTime)/60 + 10;
  1258. photoTime += 60 * num;
  1259. }
  1260. }
  1261. }
  1262. }
  1263. //拍照期间 暂停计时 这样就不用关闭定时器了
  1264. return;
  1265. }
  1266. }
  1267. //计时器
  1268. seconds++;
  1269. // NSLog(@"%d---->%d---->%@",seconds,photoTime,blueToothOrder);
  1270. if (peripheralName.length > 0) {
  1271. //------------蓝牙拍照---------------
  1272. if (seconds%3600 == 5) {
  1273. //随机出来一个拍照的时间点 取余5开始选点可以避免和获取OBD的命令冲突 加60 是为了不是第一分钟拍照命令
  1274. photoTime = seconds + (arc4random()%(endPhotoTime - startPhotoTime) + startPhotoTime)*60 + 60;
  1275. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  1276. [self saveGatherTrainDic];
  1277. }
  1278. //测试 两分钟抓拍一次
  1279. // if (seconds%120 == 5) {
  1280. // photoTime = seconds + 60;
  1281. // [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  1282. // [self saveGatherTrainDic];
  1283. // }
  1284. if (seconds == photoTime - 120) {
  1285. //拍照提示
  1286. [Tools playAudioWithString:@"两分钟后进行随机拍照,请准备"];
  1287. }
  1288. if (seconds == photoTime - 10) {
  1289. //拍照提示
  1290. if (myDelegate.isBackgroundTask) {
  1291. [self addLocalNotificationWithAudio:@"takePhotoWarn.mp3"];
  1292. }else {
  1293. [Tools playAudioWithString:@"五秒后进行拍照,请准备"];
  1294. }
  1295. }
  1296. if (seconds == photoTime - 3) {
  1297. //停止心跳包的交互
  1298. stopReplyHeart = YES;
  1299. }
  1300. if (photoTime == seconds) {//拍照
  1301. [self takePhotoByBlueTooth];
  1302. //发起拍照命令 先将拍照时间加上60S 如果验证成功 置为0。防止拍照崩溃导致一重连就拍照
  1303. photoTime += 60;
  1304. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  1305. [self saveGatherTrainDic];
  1306. }
  1307. }else {
  1308. //------------手机拍照---------------
  1309. if (seconds%3600 == 5) {
  1310. //随机出来一个拍照的时间点
  1311. //photoTime = seconds + (arc4random()%30 + 30)*60;
  1312. photoTime = seconds + (arc4random()%(endPhotoTime - startPhotoTime) + startPhotoTime)*60 + 25;
  1313. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime + 125] forKey:@"photoTime"];
  1314. [self saveGatherTrainDic];
  1315. }
  1316. if (seconds == photoTime - 120) {
  1317. //拍照提示
  1318. [Tools playAudioWithString:@"两分钟后将进行拍照检测,请准备"];
  1319. countDownBtn = [[UIButton alloc] initWithFrame:CGRectMake(kSize.width - 70, on_offBtn.y - 60, 50, 50)];
  1320. [countDownBtn borderColor:RQ_MAIN_COLOR width:1.0 cornorRadius:25.0];
  1321. [countDownBtn setTitle:@"120" textColor:RQ_MAIN_COLOR Font:FontLarger fotState:UIControlStateNormal];
  1322. [countDownBtn target:self tag:7];
  1323. [self.view addSubview:countDownBtn];
  1324. }
  1325. if (countDownBtn) {
  1326. [countDownBtn setTitle:[NSString stringWithFormat:@"%d",(int)(photoTime - seconds)] forState:UIControlStateNormal];
  1327. if (seconds == photoTime - 10){
  1328. [Tools playAudioWithString:@"十秒钟后将进入拍照页面"];
  1329. }
  1330. if (photoTime == seconds) {
  1331. [countDownBtn removeFromSuperview];
  1332. if (countDownView) {
  1333. [countDownView removeFromSuperview];
  1334. }
  1335. countDownBtn = nil;
  1336. //暂停计时
  1337. [timer setFireDate:[NSDate distantFuture]];
  1338. //进入拍照页面哈
  1339. [self takePhoto];
  1340. }
  1341. }
  1342. }
  1343. if (seconds%10 == 0) {
  1344. //这个点要采集的时候的时间 所以用这个
  1345. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1346. dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1347. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  1348. NSString *dateString = [dateFormatter stringFromDate:[NSDate date]];
  1349. [gpsDic setValue:dateString forKey:@"timestamp"];
  1350. NSDictionary *dict = [NSDictionary dictionaryWithDictionary:gpsDic];
  1351. [gpsArray addObject:dict];
  1352. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
  1353. [[UIApplication sharedApplication] setIdleTimerDisabled:peripheralName.length > 0?NO:YES];//屏幕常亮
  1354. }
  1355. int remainder = (int)seconds%60;
  1356. if (remainder == 57) {
  1357. //停止心跳包的交互
  1358. stopReplyHeart = YES;
  1359. }
  1360. if (remainder == 0)
  1361. {
  1362. //每1分钟保存一次 然后上传分钟学时 动态数据从GPSDic中获取 然后处理
  1363. NSString *maxSpeed = @"0.0000";
  1364. NSString *gpsString = @"";
  1365. NSDictionary *lastDic = nil;
  1366. CGFloat tenSecondMileage = 0.0000;
  1367. for (NSDictionary *dic in gpsArray) {
  1368. if (lastDic) {
  1369. CLLocation *newLocation = [[CLLocation alloc] initWithLatitude:[dic[@"latitude"] floatValue] longitude:[dic[@"longitude"] floatValue]];
  1370. CLLocation *lastLocation = [[CLLocation alloc] initWithLatitude:[lastDic[@"latitude"] floatValue] longitude:[lastDic[@"longitude"] floatValue]];
  1371. CLLocationDistance kilometers = [newLocation distanceFromLocation:lastLocation]/1000;
  1372. tenSecondMileage = kilometers;
  1373. mileageFloat += tenSecondMileage;
  1374. }
  1375. //最大速度
  1376. maxSpeed = [maxSpeed floatValue] > [dic[@"speed"] floatValue] ? maxSpeed : dic[@"speed"] ;
  1377. gpsString = [gpsString stringByAppendingString:[NSString stringWithFormat:@"%@,%@,%@,%@,%@,%@,0,%@,%@;",dic[@"longitude"],dic[@"latitude"],dic[@"altitude"],dic[@"course"],dic[@"timestamp"],[dic[@"speed"] floatValue] > systemMaxSpeed ? @"1" : @"0" ,dic[@"speed"],[NSString stringWithFormat:@"%.4f",tenSecondMileage]]];
  1378. lastDic = dic;
  1379. }
  1380. if (gpsString.length > 0) {
  1381. [gpsString substringToIndex:gpsString.length - 1];
  1382. }
  1383. //生成新的trainNum 先取之前的(签到时候的或者上一分钟的) 后四位序列码+1。顺便存入userDefault
  1384. NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
  1385. int OrderNum = [[[[userDefaults valueForKey:@"trainOrderNum"] componentsSeparatedByString:@","] lastObject] intValue] + 1;
  1386. NSString *trainString = @"";
  1387. if (OrderNum < 10) {
  1388. trainString = [NSString stringWithFormat:@"000%d",OrderNum];
  1389. }else if (OrderNum < 100){
  1390. trainString = [NSString stringWithFormat:@"00%d",OrderNum];
  1391. }else if (OrderNum < 1000){
  1392. trainString = [NSString stringWithFormat:@"0%d",OrderNum];
  1393. }else{
  1394. trainString = [NSString stringWithFormat:@"%d",OrderNum];
  1395. }
  1396. trainNum = [NSString stringWithFormat:@"%@%@",[trainNum substringToIndex:trainNum.length - 4],trainString];
  1397. //将trainOrderNum写入NSUserDefaults
  1398. trainOrderNum = [NSString stringWithFormat:@"%@,%d",[[[userDefaults valueForKey:@"trainOrderNum"] componentsSeparatedByString:@","] firstObject],OrderNum];
  1399. [userDefaults setValue:trainOrderNum forKey:@"trainOrderNum"];
  1400. [minuteTrainDic setValue:maxSpeed forKey:@"maxSpeed"];
  1401. [minuteTrainDic setValue:[NSString stringWithFormat:@"%.4f",mileageFloat] forKey:@"mileage"];
  1402. [minuteTrainDic setValue:gpsString forKey:@"gps"];
  1403. [minuteTrainDic setValue:trainNum forKey:@"trainNum"];
  1404. //更新gatherTrainDic数据 并存入本地
  1405. CGFloat allMileage = [gatherTrainDic[@"allMileage"] floatValue];
  1406. allMileage += mileageFloat;
  1407. [gatherTrainDic setValue:[NSString stringWithFormat:@"%.4f",allMileage] forKey:@"allMileage"];
  1408. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)seconds] forKey:@"allTime"];
  1409. [gatherTrainDic setValue:trainNum forKey:@"trainNum"];
  1410. [self saveGatherTrainDic];
  1411. NSDictionary *dict = [NSDictionary dictionaryWithDictionary:minuteTrainDic];
  1412. [DB_Helper saveSCTrainWithDic:dict];
  1413. if (peripheralName.length < 1) {
  1414. [self uploadAppTrainSingle];
  1415. }else {
  1416. [self getCarInfo];
  1417. }
  1418. //将可变参数置0 为下一分钟做准备
  1419. [gpsArray removeAllObjects];
  1420. mileageFloat = 0.0000;
  1421. lastDic = nil;
  1422. }
  1423. //手机拍的照片 十分钟补传一次
  1424. if (seconds%600 == 0) {
  1425. if (peripheralName.length == 0) {
  1426. if ([gatherTrainDic.allKeys containsObject:@"comparisonPhoto"]) {
  1427. NSArray *photoArray = gatherTrainDic[@"comparisonPhoto"];
  1428. if ([photoArray isKindOfClass:[NSArray class]]) {
  1429. NSString *method = @"comparisonPhoto";
  1430. [jiaPeiManager requestAnythingWithURL:method array:photoArray data:nil completion:^(NSDictionary * root) {
  1431. if (!root) {
  1432. return ;
  1433. }
  1434. if ([root[@"code"] isEqualToString:@"0"]) {
  1435. [gatherTrainDic removeObjectForKey:@"comparisonPhoto"];
  1436. [self saveGatherTrainDic];
  1437. }
  1438. }];
  1439. }
  1440. }
  1441. }
  1442. }
  1443. //屏幕太亮
  1444. //这里存在一个0.300000012 > 0.3的问题,所以。。(尽管你设置它为0.3,但是获取到的就是略大0.3的)
  1445. CGFloat count = [[UIScreen mainScreen] brightness] - SCREENBRIGHTLOWST;
  1446. if (count >= 0.1) {
  1447. _scrBrtTime--;
  1448. _flag = NO;//这里再次进来说明有人设置了屏幕亮度
  1449. if (_scrBrtTime == 0) {
  1450. _scrStartBright = [[UIScreen mainScreen] brightness];//记录
  1451. _flag = YES;
  1452. [[UIScreen mainScreen] setBrightness: SCREENBRIGHTLOWST];
  1453. _scrBrtTime = SCReenBRIGHTTIME;
  1454. }
  1455. }else{
  1456. _scrBrtTime = SCReenBRIGHTTIME;
  1457. _flag = NO;
  1458. //>0 && <0.1 说明相等(0.3000001 == 0.3,也说明“没有”人为设置屏幕亮度
  1459. if (count > 0) {
  1460. _flag = YES;
  1461. }
  1462. }
  1463. //更新UI上的时间
  1464. int hour = (int)seconds / 3600;
  1465. int min = (int)seconds % 3600 / 60;
  1466. int second = (int)seconds % 3600 % 60;
  1467. NSString *min_s;
  1468. NSString *second_s;
  1469. if (min<10) {
  1470. min_s=[NSString stringWithFormat:@"0%d",min];
  1471. }else{
  1472. min_s=[NSString stringWithFormat:@"%d",min];
  1473. }
  1474. if (second<10) {
  1475. second_s=[NSString stringWithFormat:@"0%d",second];
  1476. }else{
  1477. second_s=[NSString stringWithFormat:@"%d",second];
  1478. }
  1479. timeLabel.text = [NSString stringWithFormat:@"0%d:%@:%@",hour,min_s,second_s];
  1480. }
  1481. //上传分钟学时
  1482. - (void)uploadAppTrainSingle
  1483. {
  1484. if (![Util connectedToNetWork]) {
  1485. RemoveHUD();
  1486. if (isVoice) {
  1487. [Tools playAudioWithString:@"无网络连接,学时上传失败,分钟学时已保存至本地!"];
  1488. }
  1489. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1490. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1491. [formatter setDateFormat:@"HH:mm"];
  1492. NSString *timeString = [formatter stringFromDate:[NSDate date]];
  1493. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 速度%@km/h 里程%.0f米 分钟学时上传失败!",timeString,minuteTrainDic[@"maxSpeed"],[minuteTrainDic[@"obdMileage"] floatValue]*1000]];
  1494. [mainTableView reloadData];
  1495. //开启gps定位
  1496. if (!locationManager) {
  1497. [self setGPSLocationService];
  1498. [baiduLocationMan stopUpdatingLocation];
  1499. }
  1500. return;
  1501. }else{
  1502. if (locationManager) {
  1503. [locationManager stopUpdatingLocation];
  1504. locationManager.delegate = nil;
  1505. locationManager = nil;
  1506. [baiduLocationMan startUpdatingLocation];
  1507. }
  1508. }
  1509. //classId , classCode , trainNum , maxSpeed , mileage , gps , obdRotationSpeed , obdMileage
  1510. NSMutableArray *arr=[NSMutableArray array];
  1511. [arr addPro:@"stuId" Value:RQ_USER_MANAGER.currentUser.outId];
  1512. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  1513. [arr addPro:@"coachId" Value:gatherTrainDic[@"coachId"]];
  1514. [arr addPro:@"sim" Value:RQ_USER_MANAGER.currentUser.telphone];
  1515. [arr addPro:@"subject" Value:gatherTrainDic[@"subject"]];
  1516. [arr addPro:@"classId" Value:minuteTrainDic[@"classId"]];
  1517. [arr addPro:@"subjcode" Value:minuteTrainDic[@"classCode"]];
  1518. [arr addPro:@"trainNo" Value:minuteTrainDic[@"trainNum"]];
  1519. [arr addPro:@"maxSpeed" Value:minuteTrainDic[@"maxSpeed"]];
  1520. [arr addPro:@"mileAge" Value:minuteTrainDic[@"mileage"]];
  1521. [arr addPro:@"gps" Value:minuteTrainDic[@"gps"]];
  1522. [arr addPro:@"upType" Value:@"1"];
  1523. [arr addPro:@"imei" Value:[Tools getIDFV]];
  1524. //obd信息
  1525. [arr addPro:@"openObd" Value:peripheralName.length == 0 ? @"0" : @"1"];
  1526. [arr addPro:@"engineSpeed" Value:minuteTrainDic[@"obdRotationSpeed"]];
  1527. [arr addPro:@"obdMile" Value:minuteTrainDic[@"obdMileage"]];
  1528. NSString* method = @"uploadAppTrainSingle";
  1529. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  1530. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1531. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1532. [formatter setDateFormat:@"HH:mm"];
  1533. NSString *timeString = [formatter stringFromDate:[NSDate date]];
  1534. if (!root) {
  1535. if (isVoice) {
  1536. [Tools playAudioWithString:@"分钟学时上传失败!"];
  1537. }
  1538. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 速度%@km/h 里程%.0f米 分钟学时上传失败!",timeString,minuteTrainDic[@"maxSpeed"],[minuteTrainDic[@"obdMileage"] floatValue]*1000]];
  1539. [mainTableView reloadData];
  1540. return ;
  1541. }
  1542. if ([root[@"code"] isEqualToString:@"1"]) {
  1543. if (isVoice) {
  1544. [Tools playAudioWithString:[NSString stringWithFormat:@"%@,分钟学时上传失败!",root[@"body"]]];
  1545. }
  1546. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 速度%@km/h 里程%.0f米 分钟学时上传失败!",timeString,minuteTrainDic[@"maxSpeed"],[minuteTrainDic[@"obdMileage"] floatValue]*1000]];
  1547. [mainTableView reloadData];
  1548. return;
  1549. }
  1550. if ([root[@"code"] isEqualToString:@"2"]) {
  1551. [DB_Helper deleteSCTrainWithTrainNum:trainNum];
  1552. if (isVoice) {
  1553. [Tools playAudioWithString:[NSString stringWithFormat:@"%@,分钟学时上传失败!",root[@"body"]]];
  1554. }
  1555. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 速度%@km/h 里程%.0f米 分钟学时上传失败!",timeString,minuteTrainDic[@"maxSpeed"],[minuteTrainDic[@"obdMileage"] floatValue]*1000]];
  1556. [mainTableView reloadData];
  1557. return;
  1558. }
  1559. if (isVoice) {
  1560. [Tools playAudioWithString:@"分钟学时上传成功!"];
  1561. }
  1562. [dataSourceArray addObject:[NSString stringWithFormat:@"0%@ 速度%@km/h 里程%.0f米 分钟学时上传成功!",timeString,minuteTrainDic[@"maxSpeed"],[minuteTrainDic[@"obdMileage"] floatValue]*1000]];
  1563. [mainTableView reloadData];
  1564. [DB_Helper deleteSCTrainWithTrainNum:trainNum];
  1565. }];
  1566. }
  1567. //上传分钟学时(批量)
  1568. - (void)uploadAppTrainPl
  1569. {
  1570. if (![Util connectedToNetWork]) {
  1571. if (isVoice) {
  1572. [Tools playAudioWithString:@"分钟学时批量上传失败!"];
  1573. }
  1574. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1575. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1576. [formatter setDateFormat:@"HH:mm"];
  1577. NSString *timeString = [formatter stringFromDate:[NSDate date]];
  1578. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 分钟学时批量上传失败!",timeString]];
  1579. return;
  1580. }
  1581. [self.view setUserInteractionEnabled:NO];
  1582. bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, (kSize.height - 80)/2.0, kSize.width - 60, 70)];
  1583. bgLabel.backgroundColor = backGroundColor;
  1584. [bgLabel setBoardWid:5 Color:contentTextColor CornerRadius:6];
  1585. [bgLabel setText:@"分钟学时批量上传中..." Font:24 TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  1586. [[UIApplication sharedApplication].keyWindow addSubview:bgLabel];
  1587. NSMutableArray *mArr = [NSMutableArray new];;
  1588. for (NSDictionary *dic in minuteTrainArray) {
  1589. NSMutableDictionary * csDic = [NSMutableDictionary new];
  1590. [csDic setValue:gatherTrainDic[@"subject"] forKey:@"subject"];
  1591. [csDic setValue:dic[@"trainNum"] forKey:@"trainNo"];
  1592. [csDic setValue:dic[@"mileage"] forKey:@"mileAge"];
  1593. [csDic setValue:@"1" forKey:@"upType"];
  1594. [csDic setValue:RQ_USER_MANAGER.currentUser.city forKey:@"dqbh"];
  1595. [csDic setValue:gatherTrainDic[@"coachId"] forKey:@"coachId"];
  1596. [csDic setValue:dic[@"maxSpeed"] forKey:@"maxSpeed"];
  1597. [csDic setValue:dic[@"classId"] forKey:@"classId"];
  1598. [csDic setValue:dic[@"classCode"] forKey:@"subjcode"];
  1599. [csDic setValue:dic[@"gps"] forKey:@"gps"];
  1600. [csDic setValue:RQ_USER_MANAGER.currentUser.telphone forKey:@"sim"];
  1601. [csDic setValue:RQ_USER_MANAGER.currentUser.outId forKey:@"stuId"];
  1602. NSString *openObd = peripheralName.length == 0 ? @"0" : @"1";
  1603. [csDic setValue:openObd forKey:@"openObd"];
  1604. [csDic setValue:dic[@"engineSpeed"] forKey:@"engineSpeed"];
  1605. [csDic setValue:dic[@"obdMile"] forKey:@"obdMile"];
  1606. [mArr addObject:csDic];
  1607. }
  1608. NSError *error = nil;
  1609. NSData *jsonData = [NSJSONSerialization dataWithJSONObject:mArr
  1610. options:NSJSONWritingPrettyPrinted
  1611. error:&error];
  1612. NSString *jsonString = nil;
  1613. if ([jsonData length] != 0 && error == nil){
  1614. // 使用这个方法的返回,我们就可以得到想要的JSON串
  1615. jsonString = [[NSString alloc] initWithData:jsonData
  1616. encoding:NSUTF8StringEncoding];
  1617. }else{
  1618. ShowMsg(@"数据错误,请重试!");
  1619. }
  1620. NSMutableArray *arr=[NSMutableArray array];
  1621. [arr addPro:@"trains" Value:jsonString];
  1622. [arr addPro:@"imei" Value:[Tools getIDFV]];
  1623. NSString* method = @"uploadAppTrainPl";
  1624. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  1625. if (bgLabel) {
  1626. [bgLabel removeFromSuperview];
  1627. bgLabel = nil;
  1628. }
  1629. [self.view setUserInteractionEnabled:YES];
  1630. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1631. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1632. [formatter setDateFormat:@"HH:mm"];
  1633. NSString *timeString = [formatter stringFromDate:[NSDate date]];
  1634. if (!root) {
  1635. if (isVoice) {
  1636. [Tools playAudioWithString:@"分钟学时批量上传失败!"];
  1637. }
  1638. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 分钟学时批量上传失败!",timeString]];
  1639. return ;
  1640. }
  1641. if ([root[@"code"] isEqualToString:@"1"]) {
  1642. if (isVoice) {
  1643. [Tools playAudioWithString:[NSString stringWithFormat:@"%@,分钟学时批量上传失败!",root[@"body"]]];
  1644. }
  1645. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 分钟学时批量上传失败!",timeString]];
  1646. return;
  1647. }
  1648. if ([root[@"code"] isEqualToString:@"2"]) {
  1649. for (NSDictionary *dic in minuteTrainArray){
  1650. NSInteger trainNumber = [[dic[@"trainNum"] substringFromIndex:[dic[@"trainNum"] length] - 4] intValue];
  1651. int OrderNum = [[[[[NSUserDefaults standardUserDefaults] valueForKey:@"trainOrderNum"] componentsSeparatedByString:@","] lastObject] intValue];
  1652. if (trainNumber < OrderNum) {
  1653. [DB_Helper deleteSCTrainWithTrainNum:dic[@"trainNum"]];
  1654. }
  1655. }
  1656. if (isVoice) {
  1657. [Tools playAudioWithString:@"分钟学时批量上传失败!"];
  1658. }
  1659. [dataSourceArray addObject:[NSString stringWithFormat:@"1%@ 分钟学时批量上传失败!",timeString]];
  1660. return;
  1661. }
  1662. if (isVoice) {
  1663. [Tools playAudioWithString:@"分钟学时批量上传成功!"];
  1664. }
  1665. [dataSourceArray addObject:[NSString stringWithFormat:@"0%@ 分钟学时批量上传成功!",timeString]];
  1666. [DB_Helper deleteSCTrainWithClassId:gatherTrainDic[@"classId"]];
  1667. [self uploadSignOutOrClassRecord];
  1668. }];
  1669. }
  1670. - (void)showStopFailAlertWithTag:(NSInteger)tag {
  1671. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"结束计时失败,请重试!" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"确定"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  1672. if (selectedOtherButtonIndex == 0) {
  1673. [self scanQrCode];
  1674. }
  1675. }];
  1676. }
  1677. //调取相机扫描二维码
  1678. - (void)scanQrCode {
  1679. [self setScreenBright];
  1680. ScanVC *scan = [[ScanVC alloc] init];
  1681. scan.type = 1;
  1682. [scan scanBlock:^(NSDictionary *dic) {
  1683. if ([dic[@"scanType"] isEqualToString:@"allSignOut"]) {
  1684. //先关闭定时器
  1685. [timer invalidate];
  1686. timer = nil;
  1687. myDelegate.timer = nil;
  1688. //关闭蓝牙连接
  1689. [self closeBlueTooth];
  1690. //关闭后台任务
  1691. [self finishBackgroundTask];//如果没开启也可以调这个方法
  1692. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];//关闭屏幕常亮
  1693. on_offBtn.tag = 3;//表明点了结束计时 但没结束成功的情况
  1694. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  1695. [self saveGatherTrainDic];
  1696. minuteTrainArray = [DB_Helper quearySCTrainWithClassId:gatherTrainDic[@"classId"]];
  1697. if (minuteTrainArray.count > 0) {
  1698. [self uploadAppTrainPl];
  1699. } else {
  1700. [self uploadSignOutOrClassRecord];
  1701. }
  1702. } else {
  1703. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"请扫描结束计时二维码" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  1704. [self scanQrCode];
  1705. }];
  1706. }
  1707. }];
  1708. [self navPushHideTabbarToVC:scan];
  1709. }
  1710. //结束计时并上传学时汇总
  1711. - (void)uploadSignOutOrClassRecord
  1712. {
  1713. if (![Util connectedToNetWork]) {
  1714. showMsgUnconnect();
  1715. return;
  1716. }
  1717. [self.view setUserInteractionEnabled:NO];
  1718. bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(30, (kSize.height - 80)/2.0, kSize.width - 60, 70)];
  1719. bgLabel.backgroundColor = backGroundColor;
  1720. [bgLabel setBoardWid:5 Color:contentTextColor CornerRadius:6];
  1721. [bgLabel setText:@"学时汇总中..." Font:24 TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  1722. [[UIApplication sharedApplication].keyWindow addSubview:bgLabel];
  1723. NSMutableArray *arr=[NSMutableArray array];
  1724. [arr addPro:@"userId" Value:RQ_USER_MANAGER.currentUser._id];
  1725. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  1726. [arr addPro:@"coachId" Value:gatherTrainDic[@"coachId"]];
  1727. [arr addPro:@"coachSim" Value:gatherTrainDic[@"coachSim"]];
  1728. [arr addPro:@"sim" Value:RQ_USER_MANAGER.currentUser.telphone];
  1729. [arr addPro:@"subjcode" Value:gatherTrainDic[@"classCode"]];
  1730. [arr addPro:@"trainTime" Value:[NSString stringWithFormat:@"%d",[gatherTrainDic[@"allTime"] intValue]/60]];
  1731. [arr addPro:@"trainMileage" Value:gatherTrainDic[@"allMileage"]];
  1732. [arr addPro:@"aveveLocity" Value:[NSString stringWithFormat:@"%.4f",[gatherTrainDic[@"allMileage"] floatValue]/[gatherTrainDic[@"allTime"] intValue]*3600.0]];
  1733. [arr addPro:@"classNo" Value:gatherTrainDic[@"classId"]];
  1734. [arr addPro:@"isPlan" Value:gatherTrainDic[@"isPlan"]];
  1735. [arr addPro:@"orderId" Value:gatherTrainDic[@"orderId"]];
  1736. [arr addPro:@"isBill" Value:[gatherTrainDic[@"price"] intValue] == 0?@"0":@"1"];
  1737. [arr addPro:@"money" Value:gatherTrainDic[@"price"]];
  1738. [arr addPro:@"gps" Value:[NSString stringWithFormat:@"%f,%f,%@,3",myCoordinate.longitude,myCoordinate.latitude,gpsDic[@"timestamp"]]];
  1739. [arr addPro:@"openObd" Value:peripheralName.length == 0 ? @"0" : @"1"];
  1740. [arr addPro:@"obdMile" Value:gatherTrainDic[@"obdMileage"]];
  1741. NSString* method = @"uploadSignOutOrClassRecord";
  1742. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  1743. if (bgLabel) {
  1744. [bgLabel removeFromSuperview];
  1745. bgLabel = nil;
  1746. }
  1747. [self.view setUserInteractionEnabled:YES];
  1748. if (!root) {
  1749. ShowMsg(@"学时汇总失败");
  1750. [Tools playAudioWithString:@"学时汇总失败,无法结束计时"];
  1751. return ;
  1752. }
  1753. if ([root[@"code"] isEqualToString:@"1"]) {
  1754. ShowMsg(root[@"body"]);
  1755. [Tools playAudioWithString:root[@"body"]];
  1756. if ([root[@"body"] isEqualToString:@"您还未签到"]) {
  1757. [on_offBtn setTitle:@"开始计时" forState:UIControlStateNormal];
  1758. on_offBtn.tag = 1;
  1759. }
  1760. return;
  1761. }
  1762. if ([gatherTrainDic[@"allTime"] intValue] > 59) {
  1763. ShowMsg(@"学时汇总成功!");
  1764. //清除上传位置信息
  1765. [dataSourceArray removeAllObjects];
  1766. }
  1767. //将本地状态置为结束
  1768. [gatherTrainDic setValue:@"1" forKey:@"isOver"];
  1769. [gatherTrainDic removeObjectForKey:@"classId"];
  1770. [self saveGatherTrainDic];
  1771. [dataSourceArray removeAllObjects];
  1772. trainView.hidden = YES; //关闭学时状态显示
  1773. [on_offBtn setTitle:@"开始计时" forState:UIControlStateNormal];
  1774. on_offBtn.tag = 1;
  1775. [timeLabel setText:@"00:00:00" Font:44 TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  1776. if (countDownBtn) {
  1777. [countDownBtn removeFromSuperview];
  1778. countDownBtn = nil;
  1779. if (countDownView) {
  1780. [countDownView removeFromSuperview];
  1781. }
  1782. }
  1783. myDelegate.scPeriodVC = nil;
  1784. if (seconds < 60) {
  1785. //计时小于一分钟 学时无效
  1786. [Tools playAudioWithString:@"本次计时小于一分钟,计时无效"];
  1787. }else{
  1788. [Tools playAudioWithString:@"本次计时结束"];
  1789. finishDataDic = root[@"body"];
  1790. [self setNotifiViewWithDic:root[@"body"]];
  1791. }
  1792. //清空detailLab(top)
  1793. for (UILabel *detailLab in detailLabArr) {
  1794. detailLab.text = @"";
  1795. }
  1796. }];
  1797. }
  1798. -(void)setNotifiViewWithDic:(NSDictionary *)dicBody{
  1799. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
  1800. dateFormatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1801. [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
  1802. NSDate *startDate = [dateFormatter dateFromString:dicBody[@"startTime"]];
  1803. NSDate *endeDate = [dateFormatter dateFromString:dicBody[@"endTime"]];
  1804. NSTimeInterval value = [endeDate timeIntervalSinceDate:startDate];
  1805. int allHour = (int)value /3600;
  1806. int allMin = (int)value /60%60;
  1807. backView = [[UIView alloc] initWithFrame:kFrame];
  1808. backView.backgroundColor = [UIColor colorWithWhite:.01 alpha:.4];
  1809. //用window添加才能遮盖住导航栏
  1810. // [[UIApplication sharedApplication].keyWindow addSubview:backView];
  1811. [self.view addSubview:backView];
  1812. UIView *informationView = [[UIView alloc] initWithFrame:CGRectMake(20, kSize.height/2.0 - 200, kSize.width - 40, 270)];
  1813. informationView.backgroundColor = backGroundColor;
  1814. [informationView borderColor:RQlineColor width:1 cornorRadius:10];
  1815. [backView addSubview:informationView];
  1816. CGFloat x,y,w,h,wid;
  1817. wid = kSize.width - 40;
  1818. #if 0
  1819. NSString * str = [NSString stringWithFormat:@"本次实操练习起始时间为%@至%@,总时长%d时%d分,有效学时为%d时%d分, 应付金额为%@元",dicBody[@"startTime"],dicBody[@"endTime"],allHour,allMin,validHour,validMin,dicBody[@"currentMoney"]];
  1820. x = 30;
  1821. y = 50;
  1822. w = wid-60;
  1823. h = 90;
  1824. UILabel *label = [[UILabel alloc] setxywh];
  1825. [label setText:str Font:FontLarger TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  1826. label.numberOfLines = 0;
  1827. [informationView addSubview:label];
  1828. #else
  1829. x = 0;
  1830. y = 10;
  1831. w = wid;
  1832. h = 30;
  1833. UILabel *label = [[UILabel alloc] setxywh];
  1834. [label setText:@"计时结束" Font:FontTitle TextColor:kTitleColor Alignment:NSTextAlignmentCenter];
  1835. [informationView addSubview:label];
  1836. x = 20;
  1837. y = 20+h;
  1838. w = wid-40;
  1839. label = [[UILabel alloc] setxywh];
  1840. [label setText:[NSString stringWithFormat:@"开始时间: %@", dicBody[@"startTime"]] Font:NormalFont TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  1841. [informationView addSubview:label];
  1842. y += h;
  1843. label = [[UILabel alloc] setxywh];
  1844. [label setText:[NSString stringWithFormat:@"结束时间: %@", dicBody[@"endTime"]] Font:NormalFont TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  1845. [informationView addSubview:label];
  1846. y += h;
  1847. label = [[UILabel alloc] setxywh];
  1848. [label setText:[NSString stringWithFormat:@"练车时长: %d时%d分", allHour,allMin] Font:NormalFont TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  1849. [informationView addSubview:label];
  1850. y += h;
  1851. label = [[UILabel alloc] setxywh];
  1852. [label setText:[NSString stringWithFormat:@"学时有效性: %@",[dicBody[@"validTime"] integerValue] == 0?@"本次计时无效":@"本次计时有效"] Font:NormalFont TextColor:kTitleColor Alignment:NSTextAlignmentLeft];
  1853. [informationView addSubview:label];
  1854. y += 10+h;
  1855. label = [[UILabel alloc] setxywh];
  1856. CGFloat money = [dicBody[@"currentMoney"] floatValue];
  1857. NSMutableAttributedString *abs = [[NSMutableAttributedString alloc]initWithString:[NSString stringWithFormat:@"应付金额: %.2f元",money]];
  1858. [abs beginEditing];
  1859. //字体大小
  1860. [abs addAttribute:NSFontAttributeName
  1861. value:[UIFont scaleSize:17]
  1862. range:NSMakeRange(10, abs.length-10)];
  1863. [abs addAttribute:NSFontAttributeName
  1864. value:[UIFont scaleSize:15]
  1865. range:NSMakeRange(0, 10)];
  1866. //字体颜色
  1867. [abs addAttribute:NSForegroundColorAttributeName
  1868. value:[UIColor redColor]
  1869. range:NSMakeRange(10, abs.length-10)];
  1870. [abs addAttribute:NSForegroundColorAttributeName
  1871. value:kTitleColor
  1872. range:NSMakeRange(0,10)];
  1873. label.attributedText = abs;
  1874. label.textAlignment = NSTextAlignmentLeft;
  1875. [informationView addSubview:label];
  1876. #endif
  1877. if ([dicBody[@"currentMoney"] floatValue] > 0) {//有钱 支付
  1878. x = 20;
  1879. y += h + 10;
  1880. w = wid - 40;
  1881. h = 50;
  1882. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  1883. button.frame = setDIYFrame;
  1884. [button setTitle:@"确定" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  1885. [button target:self tag:8];
  1886. [informationView addSubview:button];
  1887. [button addViewWithRect:CGRectMake(0, y - 1, wid, 1)];
  1888. // x = 0;
  1889. // y += h+10;
  1890. // w = wid/2.0;
  1891. // h = 50;
  1892. // UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  1893. // button.frame = setDIYFrame;
  1894. // [button setTitle:@"暂不支付" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  1895. // [button target:self tag:8];
  1896. // [informationView addSubview:button];
  1897. //
  1898. // x = w;
  1899. // button = [UIButton buttonWithType:UIButtonTypeCustom];
  1900. // button.frame = setDIYFrame;
  1901. // [button setTitle:@"立即支付" textColor:RQ_MAIN_COLOR Font:FontLarger fotState:UIControlStateNormal];
  1902. // [button target:self tag:9];
  1903. // [informationView addSubview:button];
  1904. // [button addViewWithRect:CGRectMake(0, y - 1, wid, 1)];
  1905. // [button addViewWithRect:CGRectMake(x - .5, y, 1, h)];
  1906. }else{//没钱 评论
  1907. x = 0;
  1908. y += h+10;
  1909. w = wid/2.0;
  1910. h = 50;
  1911. UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  1912. button.frame = setDIYFrame;
  1913. [button setTitle:@"暂不评论" textColor:kTitleColor Font:FontLarger fotState:UIControlStateNormal];
  1914. [button target:self tag:8];
  1915. [informationView addSubview:button];
  1916. x = w;
  1917. button = [UIButton buttonWithType:UIButtonTypeCustom];
  1918. button.frame = setDIYFrame;
  1919. [button setTitle:@"评论" textColor:RQ_MAIN_COLOR Font:FontLarger fotState:UIControlStateNormal];
  1920. [button target:self tag:10];
  1921. [informationView addSubview:button];
  1922. [button addViewWithRect:CGRectMake(0, y - 1, wid, 1)];
  1923. [button addViewWithRect:CGRectMake(x - .5, y, 1, h)];
  1924. }
  1925. }
  1926. - (void)upLoadPhotoWithImage:(UIImage *)image{
  1927. //配置水印数组
  1928. NSDictionary *dic = @{@"up1":[NSString stringWithFormat:@"教练设备号:%@",gatherTrainDic[@"coachSim"]],@"up2":[NSString stringWithFormat:@"学员设备号:%@",RQ_USER_MANAGER.currentUser.telphone],@"down1":[NSString stringWithFormat:@"%.4f %.4f",myCoordinate.longitude,myCoordinate.latitude],@"down2":[NSString stringWithFormat:@"%@Km/h",gpsDic[@"speed"]],@"down3":gpsDic[@"timestamp"]};
  1929. //蓝牙照片不作处理
  1930. UIImage *cutImg;
  1931. if (peripheralName.length > 0) {
  1932. cutImg = image;
  1933. }else {
  1934. //剪切 然后压缩图片
  1935. NSData *data = UIImageJPEGRepresentation([image scaledAndCutToSize:CGSizeMake(240, 320)],0.5);
  1936. cutImg = [UIImage imageWithData:data];
  1937. }
  1938. //添加水印
  1939. UIImage *waterImage = [Tools watermarkImage:cutImg withDic:dic];
  1940. if (!myDelegate.isBackgroundTask) {
  1941. if (!_photoImg) {
  1942. _photoImg = [[UIImageView alloc] initWithFrame:CGRectMake(0, kSize.height - 264, 200, 150)];
  1943. _photoImg.userInteractionEnabled = YES;
  1944. UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 40)];
  1945. [label setText:@"点击移除照片" Font:Font17 TextColor:[UIColor orangeColor] Alignment:NSTextAlignmentCenter];
  1946. [_photoImg addSubview:label];
  1947. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(removeImage)];
  1948. [_photoImg addGestureRecognizer:tap];
  1949. }
  1950. [self.view addSubview:_photoImg];
  1951. _photoImg.image = cutImg;
  1952. [self performSelector:@selector(removeImage) withObject:nil afterDelay:15];
  1953. }
  1954. //转化为data 再用base64加密
  1955. NSData *data = UIImageJPEGRepresentation(waterImage,1.0);
  1956. NSString *pictureDataString = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  1957. [LoadingView showHUD];
  1958. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  1959. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  1960. [formatter setDateFormat:@"yyyyMMddHHmmss"];
  1961. NSString *dateString = [formatter stringFromDate:[NSDate date]];
  1962. NSMutableArray *arr=[NSMutableArray array];
  1963. [arr addPro:@"loginFlag" Value:isSubjectTwoSignIn?@"1":@"3"];
  1964. [arr addPro:@"content" Value:pictureDataString];//带水印的照片
  1965. [arr addPro:@"photo" Value:[UIImageJPEGRepresentation(cutImg,1.0) base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];//不带水印照片
  1966. [arr addPro:@"subjcode" Value:isSubjectTwoSignIn?classCode:gatherTrainDic[@"classCode"]];
  1967. [arr addPro:@"classId" Value:isSubjectTwoSignIn?classId:gatherTrainDic[@"classId"]];
  1968. [arr addPro:@"ptime" Value:dateString];
  1969. [arr addPro:@"stuId" Value:RQ_USER_MANAGER.currentUser.outId];
  1970. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  1971. [arr addPro:@"coachId" Value:gatherTrainDic[@"coachId"] ];
  1972. [arr addPro:@"sim" Value:RQ_USER_MANAGER.currentUser.telphone];
  1973. [arr addPro:@"gps" Value:[NSString stringWithFormat:@"%f,%f,%@,4",myCoordinate.latitude,myCoordinate.longitude,gpsDic[@"timestamp"]]];
  1974. if (![Util connectedToNetWork]) {
  1975. showMsgUnconnect();
  1976. if (isSubjectTwoSignIn) {
  1977. blueToothOrder = @"";
  1978. [Tools playAudioWithString:@"网络未连接,请检查手机网络"];
  1979. [self showAlertTakePhotoFail];
  1980. }else {
  1981. if (peripheralName.length < 1) {
  1982. [gatherTrainDic setValue:arr forKey:@"comparisonPhoto"];
  1983. [self saveGatherTrainDic];
  1984. }else {
  1985. if (myDelegate.isBackgroundTask) {
  1986. [self addLocalNotificationWithAudio:@"takePhotoNoNet.mp3"];
  1987. }else {
  1988. [Tools playAudioWithString:@"网络未连接,请检查手机网络,二十秒后重传照片"];
  1989. }
  1990. [self performSelector:@selector(upLoadPhotoWithImage:) withObject:image afterDelay:20];
  1991. }
  1992. }
  1993. return;
  1994. }
  1995. NSString *method = @"comparisonPhoto";
  1996. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  1997. RemoveHUD();
  1998. //NSLog(@"comparisonPhoto--->>>>%@",root);
  1999. if (!root) {
  2000. if (isSubjectTwoSignIn) {
  2001. [Tools playAudioWithString:@"人脸验证失败"];
  2002. [self showAlertTakePhotoFail];
  2003. }else {
  2004. if (peripheralName.length < 1) {
  2005. ShowMsg(@"上传照片失败,请重试!");
  2006. [gatherTrainDic setValue:arr forKey:@"comparisonPhoto"];
  2007. [self saveGatherTrainDic];
  2008. }else {
  2009. if (myDelegate.isBackgroundTask) {
  2010. [self addLocalNotificationWithAudio:@"takePhotoNoRespond.mp3"];
  2011. }else {
  2012. [Tools playAudioWithString:@"照片上传失败"];
  2013. }
  2014. if ([blueToothOrder containsString:@"AA2F"] ) {
  2015. [self upLoadPhotoWithImage:image];
  2016. }else {
  2017. photoTime = seconds + 600;
  2018. photoTime = photoTime + 65 - photoTime%60;
  2019. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  2020. [self saveGatherTrainDic];
  2021. }
  2022. blueToothOrder = @"";
  2023. }
  2024. }
  2025. return;
  2026. }
  2027. if ([root[@"code"] isEqualToString:@"1"]) {
  2028. if (isSubjectTwoSignIn) {
  2029. [Tools playAudioWithString:root[@"body"]];
  2030. [self showAlertTakePhotoFail];
  2031. return;
  2032. }
  2033. if (peripheralName.length < 1) {
  2034. [gatherTrainDic setValue:arr forKey:@"comparisonPhoto"];
  2035. [self saveGatherTrainDic];
  2036. }else {
  2037. //失败三次之内 发送本地通知 提示重新拍照 否则 停止计时
  2038. if (takePhotoFailCount > 2) {
  2039. takePhotoFailCount = 0;
  2040. //先关闭定时器
  2041. if (timer) {
  2042. [timer invalidate];
  2043. timer = nil;
  2044. }
  2045. myDelegate.timer = nil;
  2046. //关闭蓝牙连接
  2047. [self closeBlueTooth];
  2048. //关闭后台任务
  2049. [self finishBackgroundTask];//如果没开启也可以调这个方法
  2050. [[UIApplication sharedApplication] setIdleTimerDisabled:NO];//关闭屏幕常亮
  2051. on_offBtn.tag = 3;//表明点了结束计时 但没结束成功的情况
  2052. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  2053. [self saveGatherTrainDic];
  2054. minuteTrainArray = [DB_Helper quearySCTrainWithClassId:gatherTrainDic[@"classId"]];
  2055. if (minuteTrainArray.count > 0) {
  2056. [self uploadAppTrainPl];
  2057. }else{
  2058. [self uploadSignOutOrClassRecord];
  2059. }
  2060. if (myDelegate.isBackgroundTask) {
  2061. [self addLocalNotificationWithAudio:@"takePhotoFail.mp3"];
  2062. }else {
  2063. [Tools playAudioWithString:@"拍照失败三次,计时结束"];
  2064. }
  2065. }else {
  2066. takePhotoFailCount += 1;
  2067. //人脸比对失败,10秒后将重新拍照,请面向摄像头
  2068. if (myDelegate.isBackgroundTask) {
  2069. [self addLocalNotificationWithAudio:@"FaceRecongrise.mp3"];
  2070. }else {
  2071. [Tools playAudioWithString:[NSString stringWithFormat:@"%@,十秒后重新拍照,请面向摄像头",root[@"body"]]];
  2072. }
  2073. [self performSelector:@selector(takePhotoByBlueTooth) withObject:nil afterDelay:12];
  2074. photoTime = seconds + 120;
  2075. photoTime = photoTime + 65 - photoTime%60;
  2076. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  2077. [self saveGatherTrainDic];
  2078. }
  2079. }
  2080. return;
  2081. }
  2082. //重新拍照次数置零
  2083. blueToothOrder = @"";
  2084. takePhotoFailCount = 0;
  2085. if (isSubjectTwoSignIn) {
  2086. ShowMsg(@"人脸验证成功,开始计时!");
  2087. [Tools playAudioWithString:@"人脸验证成功,开始计时,请系好安全带"];
  2088. isSubjectTwoSignIn = NO;
  2089. [self beginTimer];
  2090. return;
  2091. }
  2092. //将拍照时间置为0
  2093. photoTime = 0;
  2094. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  2095. [self saveGatherTrainDic];
  2096. if (myDelegate.isBackgroundTask) {
  2097. [self addLocalNotificationWithAudio:@"takePhotoSucess.mp3"];
  2098. }else {
  2099. [Tools playAudioWithString:root[@"body"]];
  2100. }
  2101. }];
  2102. }
  2103. - (void)showAlertTakePhotoFail {
  2104. blueToothOrder = @"";
  2105. UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"人脸验证失败,是否重新采集照片" preferredStyle:UIAlertControllerStyleAlert];
  2106. [alert addAction:[UIAlertAction actionWithTitle:@"结束计时" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2107. //关闭定时器
  2108. if (signInTimer) {
  2109. [signInTimer invalidate];
  2110. signInTimer = nil;
  2111. }
  2112. //关闭蓝牙连接
  2113. [self closeBlueTooth];
  2114. [self forceSignOutWithDic:[NSDictionary dictionaryWithObject:classId forKey:@"classid"]];
  2115. }]];
  2116. [alert addAction:[UIAlertAction actionWithTitle:@"重新拍照" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
  2117. [self performSelector:@selector(takePhotoByBlueTooth) withObject:nil afterDelay:3];
  2118. }]];
  2119. [self presentViewController:alert animated:NO completion:nil];
  2120. }
  2121. #pragma mark - 添加本地通知
  2122. -(void)addLocalNotificationWithAudio:(NSString *)audioName{
  2123. //定义本地通知对象
  2124. UILocalNotification *notification = [[UILocalNotification alloc]init];
  2125. //设置调用时间
  2126. notification.fireDate = [NSDate date];
  2127. //设置通知属性
  2128. NSString *bodyString = @"极速驾培提醒您";
  2129. if ([audioName isEqualToString:@"takePhotoWarn.mp3"]) {
  2130. bodyString = @"5秒后进行人脸比对";
  2131. }else if ([audioName isEqualToString:@"takePhotoColloctPic.mp3"]) {
  2132. bodyString = @"拍照已完成,正在采集照片数据";
  2133. }else if ([audioName isEqualToString:@"takePhotoSucess.mp3"]) {
  2134. bodyString = @"人脸验证成功,继续计时";
  2135. }else if ([audioName isEqualToString:@"FaceRecongrise.mp3"]) {
  2136. bodyString = @"人脸验证失败,10秒后重新拍照";
  2137. }else if ([audioName isEqualToString:@"takePhotoFail.mp3"]) {
  2138. bodyString = @"人脸验证失败三次,计时结束";
  2139. }else if ([audioName isEqualToString:@"takePhotoNoNet.mp3"]) {
  2140. bodyString = @"网络未连接";
  2141. }else if ([audioName isEqualToString:@"takePhotoNoRespond.mp3"]) {
  2142. bodyString = @"照片上传失败";
  2143. }else if ([audioName isEqualToString:@"blueToothConnect.mp3"]) {
  2144. bodyString = @"车载设备连接成功";
  2145. }else if ([audioName isEqualToString:@"blueToothDisconnect.mp3"]) {
  2146. bodyString = @"车载设备已断开,计时暂停,正在尝试重新连接";
  2147. }
  2148. notification.alertBody = bodyString; //通知主体
  2149. notification.applicationIconBadgeNumber = 1;//应用程序图标右上角显示的消息数
  2150. notification.alertAction = @"打开应用"; //待机界面的滑动动作提示
  2151. notification.soundName = audioName;//收到通知时播放的声音,默认消息声音
  2152. // 通知参数
  2153. NSDictionary *userDict = [NSDictionary dictionaryWithObjectsAndKeys:@"nothing",@"ShiCaoPeriodVC_reTakePhoto", nil];
  2154. notification.userInfo = userDict;
  2155. //调用通知
  2156. [[UIApplication sharedApplication] scheduleLocalNotification:notification];
  2157. }
  2158. -(void)removeAllTheoryNotify{
  2159. NSArray *notifiArray = [[UIApplication sharedApplication] scheduledLocalNotifications];
  2160. for (UILocalNotification *local in notifiArray) {
  2161. if (local.userInfo[@"ShiCaoPeriodVC_reTakePhoto"]) {
  2162. //删除单个通知
  2163. [[UIApplication sharedApplication]cancelLocalNotification:local];
  2164. }
  2165. }
  2166. }
  2167. - (void)removeImage {
  2168. if (_photoImg) {
  2169. [_photoImg removeFromSuperview];
  2170. }
  2171. }
  2172. //生成订单
  2173. -(void)uploadReserveOrder
  2174. {
  2175. [LoadingView showHUD];
  2176. if (![Util connectedToNetWork]) {
  2177. showMsgUnconnect();
  2178. return;
  2179. }
  2180. NSMutableArray *arr=[NSMutableArray array];
  2181. [arr addPro:@"reserveId" Value:gatherTrainDic[@"reserveId"]];
  2182. [arr addPro:@"userId" Value:RQ_USER_MANAGER.currentUser._id];
  2183. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  2184. [arr addPro:@"coachId" Value:gatherTrainDic[@"coachId"]];
  2185. [arr addPro:@"sim" Value:RQ_USER_MANAGER.currentUser.telphone];
  2186. [arr addPro:@"classId" Value:classId];
  2187. NSString* method = @"uploadReserveOrder";
  2188. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  2189. RemoveHUD();
  2190. if (!root) {
  2191. ShowMsg(@"开始计时失败,请重试!");
  2192. [Tools playAudioWithString:@"开始计时失败,请虫试!"];
  2193. return;
  2194. }
  2195. if ([root[@"code"] isEqualToString:@"1"]) {
  2196. ShowMsg(root[@"body"]);
  2197. [Tools playAudioWithString:root[@"body"]];
  2198. return;
  2199. }
  2200. orderId = [root[@"body"] objectForKey:@"id"];
  2201. [gatherTrainDic setValue:orderId forKey:@"orderId"];
  2202. [gatherTrainDic setValue:[root[@"body"] objectForKey:@"subject"] forKey:@"subject"];
  2203. [gatherTrainDic setValue:[root[@"body"] objectForKey:@"price"] forKey:@"price"];
  2204. classCode = [NSString stringWithFormat:@"%@%@%@",[classCode substringToIndex:3],gatherTrainDic[@"subject"],[classCode substringFromIndex:classCode.length - 6]];
  2205. //订单正常生成 调签到接口
  2206. [self uploadStuSign];
  2207. }];
  2208. }
  2209. //删除订单
  2210. -(void)delReserveOrder
  2211. {
  2212. [LoadingView showHUD];
  2213. if (![Util connectedToNetWork]) {
  2214. showMsgUnconnect();
  2215. return;
  2216. }
  2217. NSMutableArray *arr=[NSMutableArray array];
  2218. [arr addPro:@"orderId" Value:orderId];
  2219. NSString* method = @"delReserveOrder";
  2220. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  2221. RemoveHUD();
  2222. if (!root) {
  2223. }
  2224. if ([root[@"code"] isEqualToString:@"1"]) {
  2225. return;
  2226. }
  2227. }];
  2228. }
  2229. //获取当前学员签到状态
  2230. - (void)getStuSignFlag
  2231. {
  2232. if (![Util connectedToNetWork]) {
  2233. [self isUploadLocation];
  2234. return;
  2235. }
  2236. NSMutableArray *arr=[NSMutableArray array];
  2237. [arr addPro:@"stuId" Value:RQ_USER_MANAGER.currentUser.outId];
  2238. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  2239. NSString* method = @"getStuSignFlag";
  2240. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  2241. if (!root || [root[@"code"] isEqualToString:@"1"]) {
  2242. [self isUploadLocation];
  2243. return;
  2244. }
  2245. //这个地方要根据服务器返回的学时序列 同步本地的 谁大用谁0.0
  2246. int trainNumber = [[root[@"body"] objectForKey:@"seq"] intValue];
  2247. NSString *trainNumberString = [[NSUserDefaults standardUserDefaults] valueForKey:@"trainOrderNum"]; //17-02-09,20
  2248. NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
  2249. formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
  2250. [formatter setDateFormat:@"yyMMdd"];
  2251. NSString *dateString = [formatter stringFromDate:[NSDate date]];
  2252. if (trainNumberString.length > 0) {
  2253. int oldTrainNumber = [[[trainNumberString componentsSeparatedByString:@","] lastObject] intValue];
  2254. if (trainNumber > oldTrainNumber) { //本地有重复 需要重置
  2255. [[NSUserDefaults standardUserDefaults] setValue:[NSString stringWithFormat:@"%@,%d",dateString,trainNumber] forKey:@"trainOrderNum"];
  2256. }
  2257. }else{//本地卸载数据丢失或者今天第一次计时
  2258. [[NSUserDefaults standardUserDefaults] setValue:[NSString stringWithFormat:@"%@,%d",dateString,trainNumber] forKey:@"trainOrderNum"];
  2259. }
  2260. //本地状态
  2261. [self getGatherTrainDic];
  2262. //这里接收服务器返回状态 当前训练培训训练状态 0 实操签退或模拟签退 1 实操签到 2 模拟签到 3 隔日训练 4集中理论 5终端实操
  2263. switch ([[root[@"body"] objectForKey:@"status"] integerValue]) {
  2264. case 0:
  2265. //代表签退状态 看本地是否是签退状态 如果不是 置为签退状态
  2266. if ([gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  2267. if (![gatherTrainDic[@"isOver"] isEqualToString:@"1"]) {
  2268. [gatherTrainDic setValue:@"1" forKey:@"isOver"];
  2269. [self saveGatherTrainDic];
  2270. }
  2271. }
  2272. break;
  2273. case 1:
  2274. //实操计时中 看本地是否有数据 有数据直接isUploadLocation 没有数据去调签退汇总
  2275. if (![gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  2276. //本地无数据调签退汇总
  2277. [Tools playAudioWithString:@"数据错误,系统将汇总学时,请重新实操计时"];
  2278. [self forceSignOutWithDic:root[@"body"]];
  2279. }else {
  2280. //NSLog(@"gatherTrainDic--><>%@",gatherTrainDic);
  2281. if (!gatherTrainDic[@"classId"]) {
  2282. //本地无数据调签退汇总
  2283. [self closeBlueTooth];
  2284. [Tools playAudioWithString:@"系统检测到您上次人脸验证未成功,请重新实操计时"];
  2285. [self forceSignOutWithDic:root[@"body"]];
  2286. peripheralName = @"";
  2287. [gatherTrainDic setValue:peripheralName forKey:@"blueName"];
  2288. [self saveGatherTrainDic];
  2289. }else {
  2290. if ([gatherTrainDic[@"isOver"] isEqualToString:@"1"]) {
  2291. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  2292. [self saveGatherTrainDic];
  2293. }
  2294. }
  2295. }
  2296. break;
  2297. case 2:
  2298. //模拟计时中 不能开始实操计时 并且本地不为实操计时中
  2299. isImitate = YES;
  2300. if ([gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  2301. if (![gatherTrainDic[@"isOver"] isEqualToString:@"1"]) {
  2302. [gatherTrainDic setValue:@"1" forKey:@"isOver"];
  2303. [self saveGatherTrainDic];
  2304. }
  2305. }
  2306. break;
  2307. case 3:
  2308. //隔日签到
  2309. if ([gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  2310. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  2311. [self saveGatherTrainDic];
  2312. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"您昨天还未汇总学时,请汇总后再开始新的实操学习" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:nil];
  2313. }else{
  2314. [Tools playAudioWithString:@"您昨天还未汇总学时,系统将汇总学时,请重新实操计时"];
  2315. [self forceSignOutWithDic:root[@"body"]];
  2316. }
  2317. break;
  2318. case 4:
  2319. //集中理论
  2320. isForceKeYi = YES;
  2321. break;
  2322. case 5:
  2323. //终端实操计时 不能开始实操计时 并且本地不为实操计时中
  2324. isTerminal = YES;
  2325. break;
  2326. default:
  2327. break;
  2328. }
  2329. [self isUploadLocation];
  2330. }];
  2331. }
  2332. - (void)forceSignOutWithDic:(NSDictionary *)dic
  2333. {
  2334. if (![Util connectedToNetWork]) {
  2335. return;
  2336. }
  2337. NSMutableArray *arr=[NSMutableArray array];
  2338. [arr addPro:@"classId" Value:dic[@"classid"]];
  2339. [arr addPro:@"stuId" Value:RQ_USER_MANAGER.currentUser.outId];
  2340. [arr addPro:@"dqbh" Value:RQ_USER_MANAGER.currentUser.city];
  2341. NSString* method = @"forceSignOut";
  2342. [jiaPeiManager requestAnythingWithURL:method array:arr data:nil completion:^(NSDictionary * root) {
  2343. //删除学时
  2344. if (!root || [root[@"code"] isEqualToString:@"1"]) {
  2345. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"汇总失败,请重试!" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"取消" otherButtonTitles:@[@"再试一次"] otherButtonStyles:nil showInWindow:NO completion:^(NSUInteger selectedOtherButtonIndex) {
  2346. if (selectedOtherButtonIndex == 0) {
  2347. [self getStuSignFlag];
  2348. }
  2349. }];
  2350. if (isSubjectTwoSignIn) {
  2351. on_offBtn.tag = 3;//表明点了结束计时 但没结束成功的情况
  2352. [gatherTrainDic setValue:@"2" forKey:@"isOver"];
  2353. [self saveGatherTrainDic];
  2354. [on_offBtn setTitle:@"结束计时" forState:UIControlStateNormal];
  2355. }
  2356. }else {
  2357. [dataSourceArray removeAllObjects];
  2358. if (isSubjectTwoSignIn) {
  2359. [Tools playAudioWithString:@"操作成功!"];
  2360. }
  2361. }
  2362. [DB_Helper deleteAllSCTrain];
  2363. }];
  2364. }
  2365. #pragma mark 蓝牙相关
  2366. - (void)searchBlueTooth {
  2367. dataIsLack = NO;
  2368. lastData = @"";
  2369. blueToothOrder = @"";
  2370. reOrderCount = 0;
  2371. orderNum = 0;
  2372. imageData = @"";
  2373. imgLongth = 0;
  2374. lastLongth = 0;
  2375. isLastOrder = NO;
  2376. heartSeconds = 0;
  2377. bTRequestTime = 0;
  2378. stopReplyHeart = NO;
  2379. takePhotoFailCount = 0;
  2380. //初始化蓝牙 并搜索
  2381. [self getCBCmanager];
  2382. }
  2383. //获取发动机转速、速度、里程
  2384. - (void)getCarInfo {
  2385. if (self.writeCharacteristic) {
  2386. NSString *orderString = @"BE0184";
  2387. blueToothOrder = orderString;
  2388. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:orderString]];
  2389. }
  2390. }
  2391. //发送拍照命令
  2392. - (void)takePhotoByBlueTooth {
  2393. imageData = @"";
  2394. isLastOrder = NO;
  2395. dataIsLack = NO;
  2396. lastData = @"";
  2397. imgLongth = 0;
  2398. lastLongth = 0;
  2399. orderNum = 0;
  2400. blueToothOrder = @"AA2F03040509";
  2401. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:blueToothOrder]];
  2402. }
  2403. - (void)closeBlueTooth {
  2404. if (peripheralName.length > 0) {
  2405. //断开连接
  2406. isNotPlayAudio = YES;
  2407. _haveBlueTooth = NO;
  2408. if (self.peripheral) {
  2409. [self.cbcManager cancelPeripheralConnection:self.peripheral];
  2410. }
  2411. self.peripheral.delegate = nil;
  2412. self.peripheral = nil;
  2413. self.writeCharacteristic = nil;
  2414. self.readCharacteristic = nil;
  2415. self.cbcManager = nil;
  2416. }
  2417. }
  2418. //建立一个Central Manager实例进行蓝牙管理
  2419. -(CBCentralManager *)getCBCmanager
  2420. {
  2421. if (!_cbcManager) {
  2422. _cbcManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
  2423. }
  2424. return _cbcManager;
  2425. }
  2426. //只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态
  2427. - (void)centralManagerDidUpdateState:(CBCentralManager *)central
  2428. {
  2429. switch (central.state) {
  2430. case 0:
  2431. //状态未知
  2432. //NSLog(@"CBCentralManagerStateUnknown");
  2433. break;
  2434. case 1:
  2435. //连接断开 即将重置
  2436. //NSLog(@"CBCentralManagerStateResetting");
  2437. break;
  2438. case 2:
  2439. //该平台不支持蓝牙
  2440. //NSLog(@"CBCentralManagerStateUnsupported");
  2441. break;
  2442. case 3:
  2443. //未授权蓝牙使用 hovertree.com
  2444. //NSLog(@"CBCentralManagerStateUnauthorized");
  2445. {
  2446. [self removeBlueToothLabel];
  2447. [RQ_SHARE_FUNCTION showAlertWithTitle:@"温馨提示" message:@"请在“设置”中打开蓝牙访问权限" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:nil];
  2448. }
  2449. break;
  2450. case 4:
  2451. {
  2452. //蓝牙未开启
  2453. //NSLog(@"CBCentralManagerStatePoweredOff");
  2454. if (peripheralName.length > 0) {
  2455. ShowMsg(@"请打开手机蓝牙");
  2456. [Tools playAudioWithString:@"请打开手机蓝牙"];
  2457. }
  2458. }
  2459. break;
  2460. case 5:
  2461. {
  2462. //蓝牙已开启
  2463. //NSLog(@"CBCentralManagerStatePoweredOn");
  2464. if (peripheralName.length < 1) {
  2465. return;
  2466. }
  2467. // 搜索外设
  2468. if (self.peripheral) {
  2469. return;
  2470. }
  2471. // 搜索成功之后,会调用找到外设的代理方法
  2472. [self addBlueToothLabelWithContent:[NSString stringWithFormat:@"正在连接车载设备 %@ 请稍候",peripheralName]];
  2473. [self.cbcManager scanForPeripheralsWithServices:nil // 通过某些服务筛选外设
  2474. options:nil]; // dict,条件
  2475. }
  2476. break;
  2477. default:
  2478. break;
  2479. }
  2480. }
  2481. // 发现外设后调用的方法
  2482. - (void)centralManager:(CBCentralManager *)central // 中心管理者
  2483. didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设
  2484. advertisementData:(NSDictionary *)advertisementData // 外设携带的数据
  2485. RSSI:(NSNumber *)RSSI // 外设发出的蓝牙信号强度
  2486. {
  2487. NSLog(@"搜索到的外设----><>%@----><>%@",peripheral.name,peripheralName);
  2488. //如果蓝牙名称和二维码中的一致 就可以连接了 最好能关闭蓝牙的扫描
  2489. if ([peripheral.name isEqualToString:peripheralName]) {
  2490. self.peripheral = peripheral;
  2491. [self.cbcManager stopScan];
  2492. [_cbcManager connectPeripheral:self.peripheral options:nil];
  2493. }
  2494. }
  2495. // 中心管理者连接外设成功
  2496. - (void)centralManager:(CBCentralManager *)central // 中心管理者
  2497. didConnectPeripheral:(CBPeripheral *)peripheral // 外设
  2498. {
  2499. NSLog(@"%s, line = %d, %@=连接成功", __FUNCTION__, __LINE__, peripheral.name);
  2500. [self removeBlueToothLabel];
  2501. // 连接成功之后,可以进行服务和特征的发现
  2502. // 设置外设的代理
  2503. self.peripheral.delegate = self;
  2504. // 外设发现服务,传nil代表不过滤
  2505. [self.peripheral discoverServices:nil];
  2506. isConnectBlueTooth = YES;
  2507. disconnectSeconds = 0;
  2508. if (myDelegate.isBackgroundTask) {
  2509. [self addLocalNotificationWithAudio:@"blueToothConnect.mp3"];
  2510. }else {
  2511. [Tools playAudioWithString:@"已成功连接车宰设备"];
  2512. }
  2513. }
  2514. // 外设连接失败
  2515. - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
  2516. {
  2517. isConnectBlueTooth = NO;
  2518. NSLog(@"%s, line = %d, %@=连接失败", __FUNCTION__, __LINE__, peripheral.name);
  2519. NSString *showString = @"车载设备连接失败!请重试";
  2520. NSString *audioString = @"车宰设备连接失败!请重试";
  2521. if ([gatherTrainDic isKindOfClass:[NSMutableDictionary class]]) {
  2522. if ([gatherTrainDic[@"isOver"] isEqualToString:@"0"]) {
  2523. //表明之前的计时没有结束。是恢复计时
  2524. ShowMsg(@"车载设备连接失败,计时暂停,正在尝试重新连接");
  2525. [Tools playAudioWithString:@"车宰设备连接失败,计时暂停,正在尝试重新连接"];
  2526. }
  2527. }
  2528. ShowMsg(showString);
  2529. [Tools playAudioWithString:audioString];
  2530. if (self.peripheral) {
  2531. [_cbcManager connectPeripheral:self.peripheral options:nil];
  2532. }
  2533. }
  2534. // 丢失连接
  2535. - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
  2536. {
  2537. isConnectBlueTooth = NO;
  2538. if ([blueToothOrder containsString:@"AA2F"]) {//还在执行拍照命令
  2539. if (seconds >= photoTime) {
  2540. photoTime += 60;
  2541. }
  2542. [gatherTrainDic setValue:[NSString stringWithFormat:@"%d",(int)photoTime] forKey:@"photoTime"];
  2543. [self saveGatherTrainDic];
  2544. }
  2545. NSLog(@"%s, line = %d, %@=断开连接", __FUNCTION__, __LINE__, peripheral.name);
  2546. if (self.cbcManager && self.peripheral) {
  2547. [self.cbcManager connectPeripheral:self.peripheral options:nil];
  2548. }
  2549. if (timer) {
  2550. ShowMsg(@"车载设备已断开,计时暂停,蓝牙重新连接中....");
  2551. if (myDelegate.isBackgroundTask) {
  2552. [self addLocalNotificationWithAudio:@"blueToothDisconnect.mp3"];
  2553. }else {
  2554. [Tools playAudioWithString:@"车宰设备已断开,计时暂停,正在尝试重新连接"];
  2555. }
  2556. }
  2557. }
  2558. //查找服务的所有特征
  2559. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
  2560. if (error)
  2561. {
  2562. //NSLog(@"Discovered services for %@ with error: %@", peripheral.name, [error localizedDescription]);
  2563. return;
  2564. }
  2565. //NSLog(@"services---><>%@",peripheral.services);
  2566. //服务并不是我们的目标,也没有实际意义。我们需要用的是服务下的特征,查询(每一个服务下的若干)特征
  2567. for (CBService *service in peripheral.services)
  2568. {
  2569. [peripheral discoverCharacteristics:nil forService:service];
  2570. }
  2571. }
  2572. // 发现外设服务里的特征的时候调用的代理方法(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
  2573. - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
  2574. {
  2575. /* 这里经过测试 读写全用UUID为FFE1的特征 这样收到的蓝牙回复 没有很多的多余的数据
  2576. */
  2577. for (CBCharacteristic *cha in service.characteristics) {
  2578. if ([cha.UUID isEqual:[CBUUID UUIDWithString:@"6E400003-B5A3-F393-E0A9-E50E24DCCA9E"]]) {
  2579. NSLog(@"读取特征-->>>%@",cha);
  2580. self.readCharacteristic = cha;
  2581. [peripheral setNotifyValue:YES forCharacteristic:cha];
  2582. // [peripheral readValueForCharacteristic:cha];
  2583. }
  2584. if ([cha.UUID isEqual:[CBUUID UUIDWithString:@"6E400002-B5A3-F393-E0A9-E50E24DCCA9E"]]) {
  2585. NSLog(@"写入特征-->>>%@",cha);
  2586. self.writeCharacteristic = cha;
  2587. }
  2588. }
  2589. }
  2590. - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error {
  2591. if (error) {
  2592. [peripheral setNotifyValue:YES forCharacteristic:self.readCharacteristic];
  2593. }
  2594. }
  2595. // 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法)
  2596. - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
  2597. {
  2598. if ([characteristic isEqual:self.readCharacteristic] ) {
  2599. NSString *hexString = [self convertDataToHexStr:characteristic.value];
  2600. NSLog(@"hexString---><>%@",hexString);
  2601. //与摄像头交互
  2602. if ([blueToothOrder containsString:@"AA2F"]) {
  2603. [self getDataForPictureWithString:hexString];
  2604. return;
  2605. }
  2606. //数据完整性检测
  2607. if ([hexString containsString:@"be"]) {
  2608. //数据首包
  2609. lastData = [[hexString componentsSeparatedByString:@"be"] lastObject];
  2610. if (lastData.length < 2) {
  2611. return;
  2612. }
  2613. int dataLength = [self getHexNumWithString:[lastData substringToIndex:2]];
  2614. if (lastData.length < dataLength*2 + 2) {
  2615. dataIsLack = YES;
  2616. return;
  2617. }
  2618. }else {
  2619. if (dataIsLack) {//上个包数据不够
  2620. hexString = [lastData stringByAppendingString:hexString];
  2621. lastData = hexString;
  2622. int dataLength = [self getHexNumWithString:[lastData substringToIndex:2]];
  2623. if (lastData.length < dataLength*2 + 2) {
  2624. return;
  2625. }else {
  2626. dataIsLack = NO;
  2627. hexString = [@"dsbe" stringByAppendingString:hexString];
  2628. }
  2629. }
  2630. }
  2631. //NSLog(@"检测完数据的完整性----><>%@",hexString);
  2632. // 心跳包验证
  2633. if ([hexString containsString:@"be0501"]) {//心跳包命令 执行验证然后回复
  2634. heartSeconds = 0;//得到心跳包 将这个值置零
  2635. if (stopReplyHeart) {//停止交互心跳包 (要拍照或者获取OBD数据)
  2636. return;
  2637. }
  2638. //得到数据
  2639. hexString = [[hexString componentsSeparatedByString:@"be0501"] lastObject];
  2640. if (hexString.length > 8) {
  2641. hexString = [hexString substringToIndex:8];
  2642. }
  2643. //计算数据
  2644. hexString = [self getResultWithHexString:hexString];
  2645. if (hexString.length < 14) {
  2646. NSString *OString = @"0000";
  2647. hexString = [OString stringByAppendingString:hexString];
  2648. }
  2649. //验证数据
  2650. hexString = [NSString stringWithFormat:@"be0381%@",[hexString substringFromIndex:hexString.length - 4]];
  2651. blueToothOrder = hexString;
  2652. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:hexString]];
  2653. //调接口签到
  2654. if (isNeedSignIn) {
  2655. isNeedSignIn = NO;
  2656. [self startPeriod];
  2657. }
  2658. return;
  2659. }
  2660. if ([hexString containsString:@"be0604"]) {//获取发动机转速、车速、里程
  2661. //停止回复心跳包
  2662. stopReplyHeart = NO;
  2663. hexString = [[hexString componentsSeparatedByString:@"be"] lastObject];
  2664. //获取有效字节长度 - 标示长度的字节
  2665. int stringLength = [self getHexNumWithString:[hexString substringToIndex:2]] - 1;
  2666. //获取有效的字节
  2667. hexString = [hexString substringWithRange:NSMakeRange(4, stringLength*2)];
  2668. //NSLog(@"hexString--><>%@",hexString);
  2669. NSString *obdRotationSpeed = [NSString stringWithFormat:@"%d",[self getHexNumWithString:[hexString substringWithRange:NSMakeRange(0, 4)]]];
  2670. NSString *maxSpeed = [NSString stringWithFormat:@"%d",[self getHexNumWithString:[hexString substringWithRange:NSMakeRange(4, 2)]]];
  2671. NSString *obdMileage = [NSString stringWithFormat:@"%.4f",[self getHexNumWithString:[hexString substringWithRange:NSMakeRange(6, 4)]]/1000.0];
  2672. if (!obdRotationSpeed) {
  2673. obdRotationSpeed = @"0";
  2674. }
  2675. if (!maxSpeed) {
  2676. maxSpeed = @"0";
  2677. }
  2678. if (!obdMileage) {
  2679. obdMileage = @"0";
  2680. }
  2681. //NSLog(@"obd数据--%@-%@-%@",obdRotationSpeed,maxSpeed,obdMileage);
  2682. [minuteTrainDic setValue:obdRotationSpeed forKey:@"obdRotationSpeed"];
  2683. [minuteTrainDic setValue:maxSpeed forKey:@"maxSpeed"];
  2684. [minuteTrainDic setValue:obdMileage forKey:@"obdMileage"];
  2685. [DB_Helper changeSCTrainWithTrainNum:trainNum
  2686. RotationSpeed:obdRotationSpeed
  2687. Speed:maxSpeed
  2688. Mileage:obdMileage];
  2689. //更新obdMileage数据 并存入本地
  2690. CGFloat allMileage = [gatherTrainDic[@"obdMileage"] floatValue];
  2691. allMileage += [obdMileage floatValue];
  2692. [gatherTrainDic setValue:[NSString stringWithFormat:@"%.4f",allMileage] forKey:@"obdMileage"];
  2693. [self saveGatherTrainDic];
  2694. [self uploadAppTrainSingle];//上传分钟学时
  2695. return;
  2696. }
  2697. }
  2698. }
  2699. - (void)getDataForPictureWithString:(NSString *)hexString {
  2700. //取到数据 重置状态时间
  2701. reOrderCount = 0;
  2702. bTRequestTime = 0;
  2703. //允许回复心跳包
  2704. if ([hexString containsString:@"aa2f"]) {
  2705. if (stopReplyHeart) {
  2706. stopReplyHeart = NO;
  2707. }
  2708. }
  2709. //取相片
  2710. if ([blueToothOrder containsString:@"AA2F042E"]) {
  2711. NSString *orderStr = [blueToothOrder substringWithRange:NSMakeRange(8, 4)];
  2712. if (isLastOrder) {
  2713. //接收最后一个包
  2714. if (lastData.length > 0) {
  2715. lastData = [lastData stringByAppendingString:hexString];
  2716. if (lastData.length >= lastLongth * 2) {
  2717. isLastOrder = NO;
  2718. imageData = [imageData stringByAppendingString:[lastData substringToIndex:lastLongth *2]];//将一帧的数据放在图片数据中
  2719. //NSLog(@"最后一帧%@帧的数据---><>%@------long----->%d",orderStr,[lastData substringToIndex:lastLongth *2],(int)lastData.length);
  2720. //照片数据全取出 显示照片
  2721. NSData *image = [self convertHexStrToData:imageData];
  2722. //获取到照片 上传服务器
  2723. if (image) {
  2724. [self removeBlueToothLabel];
  2725. blueToothOrder = @"AA2FWAIT";
  2726. [self upLoadPhotoWithImage:[UIImage imageWithData:image]];
  2727. }
  2728. }
  2729. }else {
  2730. if ([hexString containsString:orderStr]) {
  2731. lastData = [[hexString componentsSeparatedByString:orderStr] lastObject];
  2732. if (lastData.length > 4) {
  2733. lastData = [lastData substringFromIndex:4];//数据
  2734. }
  2735. }
  2736. }
  2737. return;
  2738. }
  2739. if ([hexString containsString:[NSString stringWithFormat:@"%@fa01",orderStr]]) {
  2740. lastData = [[hexString componentsSeparatedByString:[NSString stringWithFormat:@"%@fa01",orderStr]] lastObject];
  2741. }else {
  2742. lastData = [lastData stringByAppendingString:hexString];
  2743. if (lastData.length >= imgLongth * 2) {
  2744. imageData = [imageData stringByAppendingString:[lastData substringToIndex:imgLongth *2]];//将一帧的数据放在图片数据中
  2745. //NSLog(@"%@帧的数据---><>%@",orderStr,[lastData substringToIndex:imgLongth *2]);
  2746. lastData = @"";
  2747. orderStr = [NSString stringWithFormat:@"%@%@",[orderStr substringFromIndex:2],[orderStr substringToIndex:2]];
  2748. if ([self getHexNumWithString:orderStr] < orderNum) {//循环发送命令
  2749. if ([self getHexNumWithString:orderStr] == orderNum - 1) {
  2750. if (lastLongth > 0) {//还有一个不完整的包
  2751. isLastOrder = YES;
  2752. }else {//刚刚好 没有剩余的数据
  2753. return;
  2754. }
  2755. }
  2756. orderStr = [NSString stringWithFormat:@"%4x",[self getHexNumWithString:orderStr] + 1];////命令+1 然后转为16进制 不足4位 前边补空格
  2757. orderStr = [orderStr stringByReplacingOccurrencesOfString:@" " withString:@"0"];//将空格转换为0
  2758. orderStr = [NSString stringWithFormat:@"%@%@",[orderStr substringFromIndex:2],[orderStr substringToIndex:2]];//命令字节调换高低端
  2759. blueToothOrder = [NSString stringWithFormat:@"AA2F042E%@2F",orderStr];
  2760. //NSLog(@"自动下发命令-->>%@==----==%@",blueToothOrder,[self convertHexStrToData:blueToothOrder]);
  2761. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:blueToothOrder]];
  2762. }
  2763. }
  2764. }
  2765. return;
  2766. }
  2767. //数据完整性检测
  2768. if ([hexString containsString:@"aa2f"]) {
  2769. //数据首包
  2770. lastData = [[hexString componentsSeparatedByString:@"aa2f"] lastObject];
  2771. if (lastData.length > 0) {
  2772. if (lastData.length < 2) {
  2773. return;
  2774. }
  2775. int dataLength = [self getHexNumWithString:[lastData substringToIndex:2]];
  2776. if (lastData.length < dataLength*2 + 2) {
  2777. dataIsLack = YES;
  2778. return;
  2779. }
  2780. }else {
  2781. dataIsLack = YES;
  2782. return;
  2783. }
  2784. }else {
  2785. if (dataIsLack) {//上个包数据不够
  2786. hexString = [lastData stringByAppendingString:hexString];
  2787. lastData = hexString;
  2788. int dataLength = [self getHexNumWithString:[lastData substringToIndex:2]];
  2789. if (lastData.length < dataLength*2 + 2) {
  2790. return;
  2791. }else {
  2792. dataIsLack = NO;
  2793. hexString = [@"aa2f" stringByAppendingString:hexString];
  2794. }
  2795. }
  2796. }
  2797. //NSLog(@"检测完数据的完整性----><>%@",hexString);
  2798. if ([blueToothOrder isEqualToString:@"AA2F03040509"] && [hexString containsString:@"aa2f060a05"]) {
  2799. if (myDelegate.isBackgroundTask) {
  2800. //本地通知
  2801. [self addLocalNotificationWithAudio:@"takePhotoColloctPic.mp3"];
  2802. }else {
  2803. [Tools playAudioWithString:@"拍照已完成,正在采集照片信息,请稍后"];
  2804. }
  2805. [self addBlueToothLabelWithContent:@"正在采集照片信息..."];
  2806. NSString *str = [[hexString componentsSeparatedByString:@"2f060a05"] lastObject];
  2807. if (str.length > 6) {
  2808. str = [NSString stringWithFormat:@"%@%@%@",[str substringWithRange:NSMakeRange(4, 2)],[str substringWithRange:NSMakeRange(2, 2)],[str substringToIndex:2]];
  2809. }
  2810. imgLongth = [self getHexNumWithString:str];
  2811. //暂定一帧的大小为 01fa (506)
  2812. orderNum = imgLongth/506;
  2813. lastLongth = imgLongth%506;
  2814. //NSLog(@"图片总大小-----><>%d-----总帧数--->%d----最后一帧大小---->%d",(int)imgLongth,(int)orderNum,(int)lastLongth);
  2815. imgLongth = 506;//506是字节数
  2816. //拍照成功 发指令获取数据
  2817. isLastOrder = NO;
  2818. imageData = @"";//每次发起拍照命令前 将图片数据清空
  2819. blueToothOrder = @"AA2F042E00002E";//获取指定图像包
  2820. [self writeCharacteristic:self.peripheral characteristic:self.writeCharacteristic value:[self convertHexStrToData:blueToothOrder]];
  2821. }
  2822. }
  2823. //写数据
  2824. -(void)writeCharacteristic:(CBPeripheral *)peripheral
  2825. characteristic:(CBCharacteristic *)characteristic
  2826. value:(NSData *)value
  2827. {
  2828. //NSLog(@"写入数据-->%@",value);
  2829. [peripheral writeValue:value forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
  2830. }
  2831. // 需要注意的是特征的属性是否支持写数据
  2832. - (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
  2833. {
  2834. //NSLog(@"写入特征值-->%@",data);
  2835. /*
  2836. 打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值
  2837. 常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式
  2838. */
  2839. // 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
  2840. }
  2841. #pragma mark 16进制与NSData之间的转化 及验证算法计算
  2842. //data转换为16进制
  2843. - (NSString *)convertDataToHexStr:(NSData *)data {
  2844. if (!data || [data length] == 0) {
  2845. return @"";
  2846. }
  2847. NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
  2848. [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
  2849. unsigned char *dataBytes = (unsigned char*)bytes;
  2850. for (NSInteger i = 0; i < byteRange.length; i++) {
  2851. NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
  2852. if ([hexStr length] == 2) {
  2853. [string appendString:hexStr];
  2854. } else {
  2855. [string appendFormat:@"0%@", hexStr];
  2856. }
  2857. }
  2858. }];
  2859. return string;
  2860. }
  2861. //16进制转换为data
  2862. - (NSData *)convertHexStrToData:(NSString *)str {
  2863. if (!str || [str length] == 0) {
  2864. return nil;
  2865. }
  2866. NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
  2867. NSRange range;
  2868. if ([str length] % 2 == 0) {
  2869. range = NSMakeRange(0, 2);
  2870. } else {
  2871. range = NSMakeRange(0, 1);
  2872. }
  2873. for (NSInteger i = range.location; i < [str length]; i += 2) {
  2874. unsigned int anInt;
  2875. NSString *hexCharStr = [str substringWithRange:range];
  2876. NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
  2877. [scanner scanHexInt:&anInt];
  2878. NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
  2879. [hexData appendData:entity];
  2880. range.location += range.length;
  2881. range.length = 2;
  2882. }
  2883. return hexData;
  2884. }
  2885. - (NSString *)getResultWithHexString:(NSString *)hexString {
  2886. if (hexString.length < 8) {
  2887. //NSLog(@"验证算法输入数据错误");
  2888. return @"erroe";
  2889. }
  2890. int x = [self getHexNumWithString:[hexString substringToIndex:4]];
  2891. int y = [self getHexNumWithString:[hexString substringFromIndex:4]];
  2892. int z = 0x1323;
  2893. hexString = [NSString stringWithFormat:@"%x",(x*z+y)^z];
  2894. // //NSLog(@"%d,%d,%d,%x,%x,%x<---->%@",x,y,z,x,y,z,hexString);
  2895. return hexString;
  2896. }
  2897. /**
  2898. 将原本是16进制数字的字符串转换成计算机可以识别的int型10进制数据
  2899. */
  2900. - (int)getHexNumWithString:(NSString *)string {
  2901. int number = 0;
  2902. for (int i = 0; i < string.length; i ++) {
  2903. NSString *letterOrNumber = [string substringWithRange:NSMakeRange(string.length - i - 1, 1)];
  2904. int a = 0;
  2905. if ([letterOrNumber isEqualToString:@"a"] || [letterOrNumber isEqualToString:@"A"]) {
  2906. a = 10;
  2907. }else if ([letterOrNumber isEqualToString:@"b"] || [letterOrNumber isEqualToString:@"B"]){
  2908. a = 11;
  2909. }else if ([letterOrNumber isEqualToString:@"c"] || [letterOrNumber isEqualToString:@"C"]){
  2910. a = 12;
  2911. }else if ([letterOrNumber isEqualToString:@"d"] || [letterOrNumber isEqualToString:@"D"]){
  2912. a = 13;
  2913. }else if ([letterOrNumber isEqualToString:@"e"] || [letterOrNumber isEqualToString:@"E"]){
  2914. a = 14;
  2915. }else if ([letterOrNumber isEqualToString:@"f"] || [letterOrNumber isEqualToString:@"F"]){
  2916. a = 15;
  2917. }else {
  2918. a = [letterOrNumber intValue];
  2919. }
  2920. a = a * pow(16, i);
  2921. number += a;
  2922. }
  2923. return number;
  2924. }
  2925. //将十六进制的字符串转换成NSString则可使用如下方式
  2926. - (NSString *)convertHexStrToString:(NSString *)str {
  2927. if (!str || [str length] == 0) {
  2928. return nil;
  2929. }
  2930. NSMutableData *hexData = [[NSMutableData alloc] initWithCapacity:8];
  2931. NSRange range;
  2932. if ([str length] % 2 == 0) {
  2933. range = NSMakeRange(0, 2);
  2934. } else {
  2935. range = NSMakeRange(0, 1);
  2936. }
  2937. for (NSInteger i = range.location; i < [str length]; i += 2) {
  2938. unsigned int anInt;
  2939. NSString *hexCharStr = [str substringWithRange:range];
  2940. NSScanner *scanner = [[NSScanner alloc] initWithString:hexCharStr];
  2941. [scanner scanHexInt:&anInt];
  2942. NSData *entity = [[NSData alloc] initWithBytes:&anInt length:1];
  2943. [hexData appendData:entity];
  2944. range.location += range.length;
  2945. range.length = 2;
  2946. }
  2947. NSString *string = [[NSString alloc]initWithData:hexData encoding:NSUTF8StringEncoding];
  2948. return string;
  2949. }
  2950. //将NSString转换成十六进制的字符串则可使用如下方式
  2951. + (NSString *)convertStringToHexStr:(NSString *)str {
  2952. if (!str || [str length] == 0) {
  2953. return @"";
  2954. }
  2955. NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
  2956. NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[data length]];
  2957. [data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
  2958. unsigned char *dataBytes = (unsigned char*)bytes;
  2959. for (NSInteger i = 0; i < byteRange.length; i++) {
  2960. NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
  2961. if ([hexStr length] == 2) {
  2962. [string appendString:hexStr];
  2963. } else {
  2964. [string appendFormat:@"0%@", hexStr];
  2965. }
  2966. }
  2967. }];
  2968. return string;
  2969. }
  2970. #pragma mark 后台
  2971. //结束后台任务
  2972. - (void)finishBackgroundTask {
  2973. if (myDelegate.locationUpdateTimer) {
  2974. [myDelegate.locationUpdateTimer invalidate];
  2975. myDelegate.locationUpdateTimer = nil;
  2976. }
  2977. if (myDelegate.locationTracker) {
  2978. [myDelegate.locationTracker stopLocationTracking];
  2979. myDelegate.locationTracker = nil;
  2980. }
  2981. }
  2982. //进入后台任务
  2983. -(void)goToBackgroundTask
  2984. {
  2985. if([[UIApplication sharedApplication] backgroundRefreshStatus] == UIBackgroundRefreshStatusRestricted){
  2986. [RQ_SHARE_FUNCTION showAlertWithTitle:nil message:@"设备无法定位" alertControllerStyle:UIAlertControllerStyleAlert cancelButtonTitle:@"确定" otherButtonTitles:nil otherButtonStyles:nil showInWindow:NO completion:nil];
  2987. } else{
  2988. myDelegate.locationTracker = [[LocationTracker alloc]init];
  2989. [myDelegate.locationTracker startLocationTracking];
  2990. //Send the best location to server every 60 seconds
  2991. //You may adjust the time interval depends on the need of your app.
  2992. NSTimeInterval time = 60.0;
  2993. myDelegate.locationUpdateTimer =
  2994. [NSTimer scheduledTimerWithTimeInterval:time
  2995. target:self
  2996. selector:@selector(updateLocation)
  2997. userInfo:nil
  2998. repeats:YES];
  2999. }
  3000. }
  3001. //更新位置
  3002. -(void)updateLocation {
  3003. // //NSLog(@"updateLocation");
  3004. [myDelegate.locationTracker updateLocationToServer];
  3005. }
  3006. - (void)didReceiveMemoryWarning {
  3007. [super didReceiveMemoryWarning];
  3008. }
  3009. @end