AIFit-SDK for ble body fat scale
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MainViewController.m 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //
  2. // AIFit-Demo
  3. //
  4. // Created by iot_wz on 2018/9/1.
  5. // Copyright © 2018年 iot_wz. All rights reserved.
  6. //
  7. #import "MainViewController.h"
  8. #import "SearchDeviceVC.h"
  9. #import <InetBleSDK/InetBleSDK.h>
  10. #import "AppUser.h"
  11. #import "SetUserViewController.h"
  12. @interface MainViewController () <AnalysisBLEDataManagerDelegate, INBluetoothManagerDelegate,UITableViewDataSource,UITableViewDelegate>
  13. @property (weak, nonatomic) IBOutlet UIButton *connectedDevicesButton;
  14. @property (weak, nonatomic) IBOutlet UILabel *userInfoLabel;
  15. @property (weak, nonatomic) IBOutlet UISegmentedControl *unitSegmentedControl;
  16. @property (weak, nonatomic) IBOutlet UITableView *tableView;
  17. @property (nonatomic, strong) NSArray *itemNameArr;
  18. @property (nonatomic, strong) NSMutableArray *itemValueArr;
  19. @property (weak, nonatomic) IBOutlet UILabel *tipLB;
  20. @property (nonatomic, strong) UserInfoModel *currentInfoModel;
  21. @property (nonatomic, strong) DeviceModel *targetDeviceModel;
  22. @property (nonatomic, strong) AppUser *appUser;
  23. @end
  24. @implementation MainViewController
  25. - (NSArray *)itemNameArr {
  26. if (_itemNameArr == nil) {
  27. _itemNameArr = @[
  28. @"weight:",
  29. @"BMI:",
  30. @"fatRate:",
  31. @"muscle:",
  32. @"moisture:",
  33. @"boneMass:",
  34. @"BMR:",
  35. @"visceralFat:",
  36. @"subcutaneousFat:",
  37. @"proteinRate:",
  38. @"physicalAge:",
  39. @"ADC:",
  40. @"temperature:",
  41. @"standardWeight:",
  42. @"weightControl:",
  43. @"fatMass:",
  44. @"weightWithoutFat:",
  45. @"muscleMass:",
  46. @"proteinMass:",
  47. @"fatlevel:"
  48. ];
  49. }
  50. return _itemNameArr;
  51. }
  52. - (NSMutableArray *)itemValueArr {
  53. if (_itemValueArr == nil) {
  54. _itemValueArr = [[NSMutableArray alloc] init];
  55. for (int i = 0; i < self.itemNameArr.count; i++) {
  56. [_itemValueArr addObject:@"--.--"];
  57. }
  58. }
  59. return _itemValueArr;
  60. }
  61. #pragma mark ============ life circle ==============
  62. - (void)viewDidLoad {
  63. [super viewDidLoad];
  64. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(makeViewEndEditing)];
  65. [self.view addGestureRecognizer:tap];
  66. //set default value
  67. _appUser = [[AppUser alloc] init];
  68. _appUser.sex = 1;
  69. _appUser.age = 25;
  70. _appUser.height = 175;
  71. _appUser.weightKg = 0.0;
  72. _appUser.adc = 0;
  73. _userInfoLabel.text = [NSString stringWithFormat:@" sex:%d\n age:%d\n height:%d\n weight:%.1f\n adc:%d",_appUser.sex,_appUser.age,_appUser.height,_appUser.weightKg,_appUser.adc];
  74. self.tableView.dataSource = self;
  75. self.tableView.delegate = self;
  76. //reset label
  77. [self resetLBText];
  78. }
  79. - (void)makeViewEndEditing {
  80. [self.view endEditing:YES];
  81. }
  82. - (void)viewWillAppear:(BOOL)animated {
  83. [super viewWillAppear:animated];
  84. //setDelegate
  85. [AnalysisBLEDataManager shareManager].infoDelegate = self;
  86. [INBluetoothManager shareManager].delegate = self;
  87. [INBluetoothManager enableSDKLogs:YES]; //open log switch
  88. }
  89. -(void)resetLBText {
  90. self.itemValueArr = nil;
  91. self.tipLB.text = @"--.--";
  92. }
  93. #pragma mark ============ click action ==============
  94. - (IBAction)Click_Ble:(id)sender {
  95. if ([INBluetoothManager shareManager].bleState != CBCentralManagerStatePoweredOn) {
  96. [[[UIAlertView alloc] initWithTitle:@"Alert" message:@"BLE closed, pls open!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
  97. return;
  98. }
  99. SearchDeviceVC *searchVC = [[SearchDeviceVC alloc]init];
  100. __weak typeof(self) weakSelf = self;
  101. searchVC.didSelectDeviceBlock = ^(DeviceModel *device) {
  102. [weakSelf backFromSearchDeviceVC:device];
  103. };
  104. searchVC.gobackBlock = ^{
  105. [weakSelf.connectedDevicesButton setTitle:@"Connect Device" forState:UIControlStateNormal];
  106. };
  107. searchVC.modalPresentationStyle = UIModalPresentationFullScreen;
  108. [self presentViewController:searchVC animated:YES completion:nil];
  109. }
  110. - (void)backFromSearchDeviceVC:(DeviceModel *)device {
  111. NSLog(@"---device:%@",device);
  112. _targetDeviceModel = device;
  113. [self.connectedDevicesButton setTitle:device.deviceAddress forState:UIControlStateNormal];
  114. if (device.acNumber.intValue < 2) { //0、1 is broadcast scale
  115. [[INBluetoothManager shareManager] handleDataForBroadScale:device];
  116. } else { //2、3 is Link scale
  117. [[INBluetoothManager shareManager] connectToLinkScale:device];
  118. }
  119. }
  120. - (IBAction)editUser:(id)sender {
  121. SetUserViewController *vc = [[SetUserViewController alloc] init];
  122. vc.user = _appUser;
  123. __weak typeof(self) weakSelf = self;
  124. vc.editUserCallBack = ^{
  125. weakSelf.userInfoLabel.text = [NSString stringWithFormat:@" sex:%d\n age:%d\n height:%d\n weight:%.1f\n adc:%d",weakSelf.appUser.sex,weakSelf.appUser.age,weakSelf.appUser.height,weakSelf.appUser.weightKg,weakSelf.appUser.adc];
  126. [weakSelf syncWeighingUserToBle];
  127. //If no need offline history function, do not call this method
  128. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  129. [weakSelf syncOfflineUserListToBle];
  130. });
  131. };
  132. [self presentViewController:vc animated:YES completion:nil];
  133. }
  134. - (IBAction)getOfflineHistory:(id)sender {
  135. //request history (If no need offline history function, do not call this method)
  136. [[WriteToBLEManager shareManager] requestOfflineHistory];
  137. }
  138. // click sync user button
  139. - (void)syncWeighingUserToBle {
  140. if (_targetDeviceModel.acNumber.intValue < 2) {
  141. //broadcast scale do not need to sync user
  142. } else {
  143. //connect scale must input sex、weight、age
  144. BLEUser *user = [[BLEUser alloc] init];
  145. user.userSex = _appUser.sex;
  146. user.userAge = _appUser.age;
  147. user.userHeight = _appUser.height;
  148. [[WriteToBLEManager shareManager] syncWeighingUser:user];
  149. }
  150. }
  151. /// If no need offline history function, do not call this method
  152. - (void)syncOfflineUserListToBle {
  153. if (_targetDeviceModel.acNumber.intValue < 2) {
  154. //broadcast scale can not receive write command
  155. } else {
  156. BLEUser *user = [[BLEUser alloc] init];
  157. user.userSex = _appUser.sex;
  158. user.userAge = _appUser.age;
  159. user.userHeight = _appUser.height;
  160. user.userWeight = _appUser.weightKg; //note
  161. user.userAdc = _appUser.adc; //note
  162. [[WriteToBLEManager shareManager] sendOfflineUserListToBle:@[user]]; //you can add more than one user to array
  163. }
  164. }
  165. // click change unit segmentedControl
  166. - (IBAction)ChooseUnit:(UISegmentedControl *)Segmented {
  167. if (_targetDeviceModel.acNumber.intValue < 2) {
  168. //broadcast scale can not receive write command
  169. } else {
  170. [[WriteToBLEManager shareManager] write_To_Unit:Segmented.selectedSegmentIndex];
  171. NSString *weightShow = [self getWeightShowStr:_currentInfoModel unit:_unitSegmentedControl.selectedSegmentIndex];
  172. [self.itemValueArr replaceObjectAtIndex:0 withObject:weightShow];
  173. }
  174. }
  175. #pragma mark ============ BluetoothManagerDelegate ==============
  176. - (void)BluetoothManager:(INBluetoothManager *)manager updateCentralManagerState:(BluetoothManagerState)state {
  177. switch (state) {
  178. case BluetoothManagerState_PowerOn:
  179. {
  180. _tipLB.text = @"BLE open";
  181. break;
  182. }
  183. case BluetoothManagerState_PowerOff:
  184. {
  185. _tipLB.text = @"BLE closed";
  186. break;
  187. }
  188. case BluetoothManagerState_Disconnect:
  189. {
  190. _tipLB.text = @"BLE Disconnect";
  191. break;
  192. }
  193. default:
  194. break;
  195. }
  196. }
  197. //only used for link scale
  198. - (void)BluetoothManager:(INBluetoothManager *)manager didConnectDevice:(DeviceModel *)deviceModel {
  199. _targetDeviceModel = deviceModel;
  200. }
  201. #pragma mark - AnalysisBLEDataManagerDelegate
  202. - (void)AnalysisBLEDataManager:(AnalysisBLEDataManager *)analysisManager updateBleDataAnalysisStatus:(BleDataAnalysisStatus)bleDataAnalysisStatus {
  203. switch (bleDataAnalysisStatus) {
  204. case BleDataAnalysisStatus_SyncTimeSuccess:
  205. {
  206. _tipLB.text = @"sync time success";
  207. //set unit
  208. [self ChooseUnit:self.unitSegmentedControl];
  209. //then sync user to be weighing
  210. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  211. [self syncWeighingUserToBle];
  212. });
  213. // //sync offline userlist(If no need offline history function, do not call this method)
  214. // dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  215. // [self syncOfflineUserListToBle];
  216. // });
  217. break;
  218. }
  219. case BleDataAnalysisStatus_SyncTimeFailed:
  220. {
  221. _tipLB.text = @"sync time failed";
  222. break;
  223. }
  224. case BleDataAnalysisStatus_SyncUserSuccess:
  225. {
  226. _tipLB.text = @"sync weighing user success";
  227. break;
  228. }
  229. case BleDataAnalysisStatus_SyncUserFailed:
  230. {
  231. _tipLB.text = @"sync weighing user failed";
  232. break;
  233. }
  234. case BleDataAnalysisStatus_UnstableWeight:
  235. {
  236. _tipLB.text = @"measuring...\nUnstable Weight";
  237. break;
  238. }
  239. case BleDataAnalysisStatus_StableWeight:
  240. {
  241. _tipLB.text = @"Stable Weight";
  242. break;
  243. }
  244. case BleDataAnalysisStatus_MeasureComplete:
  245. {
  246. _tipLB.text = @"measure complete";
  247. break;
  248. }
  249. case BleDataAnalysisStatus_AdcError:
  250. {
  251. _tipLB.text = @"adc measure failed";
  252. break;
  253. }
  254. case BleDataAnalysisStatus_LightOff:
  255. {
  256. _tipLB.text = @"your linkScale light off";
  257. break;
  258. }
  259. default:
  260. break;
  261. }
  262. }
  263. - (void)AnalysisBLEDataManager:(AnalysisBLEDataManager *)analysisManager updateMeasureUserInfo:(UserInfoModel *)infoModel {
  264. NSLog(@"---infoModel:%@",infoModel);
  265. _currentInfoModel = infoModel;
  266. if (_currentInfoModel.measureStatus == MeasureStatus_Complete && _currentInfoModel.weightsum > 0 && _currentInfoModel.newAdc > 0) { //Measure Complete
  267. float weight = _currentInfoModel.weightsum/pow(10, _currentInfoModel.weightOriPoint);//6895->68.95
  268. float adc = _currentInfoModel.newAdc;
  269. _appUser.weightKg = weight;
  270. _appUser.adc = adc;
  271. _userInfoLabel.text = [NSString stringWithFormat:@" sex:%d\n age:%d\n height:%d\n weight:%.1f\n adc:%d",_appUser.sex,_appUser.age,_appUser.height,_appUser.weightKg,_appUser.adc];
  272. if (_targetDeviceModel.acNumber.intValue < 2) { //BroadScale BM15 mesure complete
  273. AlgorithmModel *algModel = [AlgorithmSDK getBodyfatWithWeight:weight adc:adc sex:_appUser.sex age:_appUser.age height:_appUser.height];
  274. NSLog(@"---BM15 AlgorithmModel: %@",algModel);
  275. _currentInfoModel.fatRate = algModel.bfr.floatValue;
  276. _currentInfoModel.BMI = algModel.bmi.floatValue;
  277. _currentInfoModel.moisture = algModel.vwc.floatValue;
  278. _currentInfoModel.muscle = algModel.rom.floatValue;
  279. _currentInfoModel.BMR = algModel.bmr.floatValue;
  280. _currentInfoModel.boneMass = algModel.bm.floatValue;
  281. _currentInfoModel.visceralFat = algModel.uvi.floatValue;
  282. _currentInfoModel.proteinRate = algModel.pp.floatValue;
  283. _currentInfoModel.physicalAge = algModel.physicalAge.floatValue;
  284. _currentInfoModel.subcutaneousFat = algModel.sfr.floatValue;
  285. //refresh
  286. [self refreshTableView];
  287. } else { //connect scale measure complete
  288. [self syncWeighingUserToBle];
  289. // If no need offline history function, do not call this method
  290. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  291. [self syncOfflineUserListToBle];
  292. });
  293. }
  294. ///When user is an athlete, calling this method will modify the body fat data.
  295. //[_currentInfoModel changeToBeAthleteWithSex:_appUser.sex];
  296. //NSLog(@"---infoModel222:%@",infoModel);
  297. }
  298. //refresh
  299. [self refreshTableView];
  300. }
  301. - (void)refreshTableView {
  302. NSString *weightShow = [self getWeightShowStr:_currentInfoModel unit:_unitSegmentedControl.selectedSegmentIndex];
  303. [self.itemValueArr replaceObjectAtIndex:0 withObject:weightShow];
  304. [self.itemValueArr replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.BMI]];
  305. [self.itemValueArr replaceObjectAtIndex:2 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.fatRate]];
  306. [self.itemValueArr replaceObjectAtIndex:3 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.muscle]];
  307. [self.itemValueArr replaceObjectAtIndex:4 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.moisture]];
  308. [self.itemValueArr replaceObjectAtIndex:5 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.boneMass]];
  309. [self.itemValueArr replaceObjectAtIndex:6 withObject:[NSString stringWithFormat:@"%.1fkcal",_currentInfoModel.BMR]];
  310. [self.itemValueArr replaceObjectAtIndex:7 withObject:[NSString stringWithFormat:@"%.0f",_currentInfoModel.visceralFat]];
  311. [self.itemValueArr replaceObjectAtIndex:8 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.subcutaneousFat]];
  312. [self.itemValueArr replaceObjectAtIndex:9 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.proteinRate]];
  313. [self.itemValueArr replaceObjectAtIndex:10 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.physicalAge]];
  314. [self.itemValueArr replaceObjectAtIndex:11 withObject:[NSString stringWithFormat:@"%.0f",_currentInfoModel.newAdc]];
  315. [self.itemValueArr replaceObjectAtIndex:12 withObject:[NSString stringWithFormat:@"%.1f°C",_currentInfoModel.temperature]];
  316. float weight = _currentInfoModel.weightsum/pow(10, _currentInfoModel.weightOriPoint);//6895->68.95
  317. int sex = _appUser.sex;
  318. int height = _appUser.height;
  319. NSString *bfr = [NSString stringWithFormat:@"%.1f",_currentInfoModel.fatRate];
  320. NSString *rom = [NSString stringWithFormat:@"%.1f%",_currentInfoModel.muscle];
  321. NSString *pp = [NSString stringWithFormat:@"%.1f%",_currentInfoModel.proteinRate];
  322. BfsCalculateItem *item = [BfsCalculateSDK getBodyfatItemWithSex:sex height:height weight:weight bfr:bfr rom:rom pp:pp];
  323. [self.itemValueArr replaceObjectAtIndex:13 withObject:[NSString stringWithFormat:@"%.1fkg",item.standardWeight]];
  324. [self.itemValueArr replaceObjectAtIndex:14 withObject:[NSString stringWithFormat:@"%.1fkg",item.weightControl]];
  325. [self.itemValueArr replaceObjectAtIndex:15 withObject:[NSString stringWithFormat:@"%.1fkg",item.fatMass]];
  326. [self.itemValueArr replaceObjectAtIndex:16 withObject:[NSString stringWithFormat:@"%.1fkg",item.weightWithoutFat]];
  327. [self.itemValueArr replaceObjectAtIndex:17 withObject:[NSString stringWithFormat:@"%.1fkg",item.muscleMass]];
  328. [self.itemValueArr replaceObjectAtIndex:18 withObject:[NSString stringWithFormat:@"%.1fkg",item.proteinMass]];
  329. [self.itemValueArr replaceObjectAtIndex:19 withObject:[NSString stringWithFormat:@"%zd",item.fatlevel]];
  330. [self.tableView reloadData];
  331. }
  332. //If no need offline history function, do not implement this callback
  333. - (void)AnalysisBLEDataManager:(AnalysisBLEDataManager *)analysisManager backOfflineHistorys:(NSMutableArray <UserInfoModel *> *)historysMutableArr {
  334. // _tipLB.text = [NSString stringWithFormat:@"Got %zd offline historys! check sdk log.",historysMutableArr.count];
  335. //
  336. // for (UserInfoModel *info in historysMutableArr) {
  337. // NSLog(@"---get offline history:\n %@",info);
  338. // }
  339. NSString *title = [NSString stringWithFormat:@"Got %zd offline historys!",historysMutableArr.count];
  340. NSMutableString *strM = [NSMutableString string];
  341. for (UserInfoModel *info in historysMutableArr) {
  342. NSLog(@"---get offline history:\n %@",info);
  343. [strM appendString:[NSString stringWithFormat:@"%@\n-----------------\n",info]];
  344. }
  345. [[[UIAlertView alloc] initWithTitle:title message:strM delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
  346. }
  347. #pragma mark ============ tableView datasource ==============
  348. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  349. return self.itemNameArr.count;
  350. }
  351. static NSString * const CellID = @"CellID";
  352. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  353. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];
  354. if (cell == nil) {
  355. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellID];
  356. cell.textLabel.textColor = [UIColor blackColor];
  357. cell.detailTextLabel.textColor = [UIColor blueColor];
  358. }
  359. //赋值
  360. cell.textLabel.text = self.itemNameArr[indexPath.row];
  361. cell.detailTextLabel.text = self.itemValueArr[indexPath.row];
  362. return cell;
  363. }
  364. #pragma mark ============ handle weight point ==============
  365. // change weight unit
  366. - (NSString *)getWeightShowStr:(UserInfoModel *)infoModel unit:(NSInteger)unit {
  367. float weight = infoModel.weightsum/pow(10, infoModel.weightOriPoint);//6895->68.95
  368. NSString *formatStr = [NSString stringWithFormat:@"%%.%df",infoModel.weightKgPoint]; //@"%.1f"
  369. NSString *showWeight = @"";
  370. if (unit == 0) {
  371. formatStr = [formatStr stringByAppendingString:@"kg"]; //@"%.1fkg"
  372. showWeight = [NSString stringWithFormat:formatStr,weight];
  373. } else if (unit == 1) {
  374. formatStr = [formatStr stringByAppendingString:@"lb"]; //@"%.1flb"
  375. showWeight = [NSString stringWithFormat:formatStr,weight*2.2046226f];
  376. } else if (unit == 2) {
  377. showWeight = [self kg2St:weight]; //st(lb/14): **lb:**st
  378. } else if (unit == 3) {
  379. formatStr = [formatStr stringByAppendingString:@"斤"]; //@"%.1f斤"
  380. showWeight = [NSString stringWithFormat:formatStr,weight*2];
  381. }else {
  382. formatStr = [formatStr stringByAppendingString:@"kg"]; //@"%.1fkg"
  383. showWeight = [NSString stringWithFormat:formatStr,weight];
  384. }
  385. return showWeight;
  386. }
  387. - (NSString *)kg2St:(float)kgWeight {
  388. NSString *oneString = [NSString stringWithFormat:@"%d",(int)(kgWeight*2.2046226f)/14];
  389. NSString *twoString = [NSString stringWithFormat:@"%d",((int)(kgWeight*2.2046226f)%14)];
  390. return [NSString stringWithFormat:@"%@:%@st",oneString,twoString];
  391. }
  392. @end