AIFit-SDK for ble body fat scale
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

MainViewController.m 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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. [self refreshTableView];
  267. if (_currentInfoModel.measureStatus == MeasureStatus_Complete && _currentInfoModel.weightsum > 0 && _currentInfoModel.newAdc > 0) { //Measure Complete
  268. float weight = _currentInfoModel.weightsum/pow(10, _currentInfoModel.weightOriPoint);//6895->68.95
  269. float adc = _currentInfoModel.newAdc;
  270. _appUser.weightKg = weight;
  271. _appUser.adc = adc;
  272. _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];
  273. if (_targetDeviceModel.acNumber.intValue < 2) { //BroadScale BM15 mesure complete
  274. AlgorithmModel *algModel = [AlgorithmSDK getBodyfatWithWeight:weight adc:adc sex:_appUser.sex age:_appUser.age height:_appUser.height];
  275. NSLog(@"---BM15 AlgorithmModel: %@",algModel);
  276. _currentInfoModel.fatRate = algModel.bfr.floatValue;
  277. _currentInfoModel.BMI = algModel.bmi.floatValue;
  278. _currentInfoModel.moisture = algModel.vwc.floatValue;
  279. _currentInfoModel.muscle = algModel.rom.floatValue;
  280. _currentInfoModel.BMR = algModel.bmr.floatValue;
  281. _currentInfoModel.boneMass = algModel.bm.floatValue;
  282. _currentInfoModel.visceralFat = algModel.uvi.floatValue;
  283. _currentInfoModel.proteinRate = algModel.pp.floatValue;
  284. _currentInfoModel.physicalAge = algModel.physicalAge.floatValue;
  285. _currentInfoModel.subcutaneousFat = algModel.sfr.floatValue;
  286. //refresh
  287. [self refreshTableView];
  288. } else { //connect scale measure complete
  289. [self syncWeighingUserToBle];
  290. // If no need offline history function, do not call this method
  291. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  292. [self syncOfflineUserListToBle];
  293. });
  294. }
  295. }
  296. }
  297. - (void)refreshTableView {
  298. NSString *weightShow = [self getWeightShowStr:_currentInfoModel unit:_unitSegmentedControl.selectedSegmentIndex];
  299. [self.itemValueArr replaceObjectAtIndex:0 withObject:weightShow];
  300. [self.itemValueArr replaceObjectAtIndex:1 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.BMI]];
  301. [self.itemValueArr replaceObjectAtIndex:2 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.fatRate]];
  302. [self.itemValueArr replaceObjectAtIndex:3 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.muscle]];
  303. [self.itemValueArr replaceObjectAtIndex:4 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.moisture]];
  304. [self.itemValueArr replaceObjectAtIndex:5 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.boneMass]];
  305. [self.itemValueArr replaceObjectAtIndex:6 withObject:[NSString stringWithFormat:@"%.1fkcal",_currentInfoModel.BMR]];
  306. [self.itemValueArr replaceObjectAtIndex:7 withObject:[NSString stringWithFormat:@"%.0f",_currentInfoModel.visceralFat]];
  307. [self.itemValueArr replaceObjectAtIndex:8 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.subcutaneousFat]];
  308. [self.itemValueArr replaceObjectAtIndex:9 withObject:[NSString stringWithFormat:@"%.1f%",_currentInfoModel.proteinRate]];
  309. [self.itemValueArr replaceObjectAtIndex:10 withObject:[NSString stringWithFormat:@"%.1f",_currentInfoModel.physicalAge]];
  310. [self.itemValueArr replaceObjectAtIndex:11 withObject:[NSString stringWithFormat:@"%.0f",_currentInfoModel.newAdc]];
  311. [self.itemValueArr replaceObjectAtIndex:12 withObject:[NSString stringWithFormat:@"%.1f°C",_currentInfoModel.temperature]];
  312. float weight = _currentInfoModel.weightsum/pow(10, _currentInfoModel.weightOriPoint);//6895->68.95
  313. int sex = _appUser.sex;
  314. int height = _appUser.height;
  315. NSString *bfr = [NSString stringWithFormat:@"%.1f",_currentInfoModel.fatRate];
  316. NSString *rom = [NSString stringWithFormat:@"%.1f%",_currentInfoModel.muscle];
  317. NSString *pp = [NSString stringWithFormat:@"%.1f%",_currentInfoModel.proteinRate];
  318. BfsCalculateItem *item = [BfsCalculateSDK getBodyfatItemWithSex:sex height:height weight:weight bfr:bfr rom:rom pp:pp];
  319. [self.itemValueArr replaceObjectAtIndex:13 withObject:[NSString stringWithFormat:@"%.1fkg",item.standardWeight]];
  320. [self.itemValueArr replaceObjectAtIndex:14 withObject:[NSString stringWithFormat:@"%.1fkg",item.weightControl]];
  321. [self.itemValueArr replaceObjectAtIndex:15 withObject:[NSString stringWithFormat:@"%.1fkg",item.fatMass]];
  322. [self.itemValueArr replaceObjectAtIndex:16 withObject:[NSString stringWithFormat:@"%.1fkg",item.weightWithoutFat]];
  323. [self.itemValueArr replaceObjectAtIndex:17 withObject:[NSString stringWithFormat:@"%.1fkg",item.muscleMass]];
  324. [self.itemValueArr replaceObjectAtIndex:18 withObject:[NSString stringWithFormat:@"%.1fkg",item.proteinMass]];
  325. [self.itemValueArr replaceObjectAtIndex:19 withObject:[NSString stringWithFormat:@"%zd",item.fatlevel]];
  326. [self.tableView reloadData];
  327. }
  328. //If no need offline history function, do not implement this callback
  329. - (void)AnalysisBLEDataManager:(AnalysisBLEDataManager *)analysisManager backOfflineHistorys:(NSMutableArray <UserInfoModel *> *)historysMutableArr {
  330. // _tipLB.text = [NSString stringWithFormat:@"Got %zd offline historys! check sdk log.",historysMutableArr.count];
  331. //
  332. // for (UserInfoModel *info in historysMutableArr) {
  333. // NSLog(@"---get offline history:\n %@",info);
  334. // }
  335. NSString *title = [NSString stringWithFormat:@"Got %zd offline historys!",historysMutableArr.count];
  336. NSMutableString *strM = [NSMutableString string];
  337. for (UserInfoModel *info in historysMutableArr) {
  338. NSLog(@"---get offline history:\n %@",info);
  339. [strM appendString:[NSString stringWithFormat:@"%@\n-----------------\n",info]];
  340. }
  341. [[[UIAlertView alloc] initWithTitle:title message:strM delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil, nil] show];
  342. }
  343. #pragma mark ============ tableView datasource ==============
  344. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  345. return self.itemNameArr.count;
  346. }
  347. static NSString * const CellID = @"CellID";
  348. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  349. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellID];
  350. if (cell == nil) {
  351. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellID];
  352. cell.textLabel.textColor = [UIColor blackColor];
  353. cell.detailTextLabel.textColor = [UIColor blueColor];
  354. }
  355. //赋值
  356. cell.textLabel.text = self.itemNameArr[indexPath.row];
  357. cell.detailTextLabel.text = self.itemValueArr[indexPath.row];
  358. return cell;
  359. }
  360. #pragma mark ============ handle weight point ==============
  361. // change weight unit
  362. - (NSString *)getWeightShowStr:(UserInfoModel *)infoModel unit:(NSInteger)unit {
  363. float weight = infoModel.weightsum/pow(10, infoModel.weightOriPoint);//6895->68.95
  364. NSString *formatStr = [NSString stringWithFormat:@"%%.%df",infoModel.weightKgPoint]; //@"%.1f"
  365. NSString *showWeight = @"";
  366. if (unit == 0) {
  367. formatStr = [formatStr stringByAppendingString:@"kg"]; //@"%.1fkg"
  368. showWeight = [NSString stringWithFormat:formatStr,weight];
  369. } else if (unit == 1) {
  370. formatStr = [formatStr stringByAppendingString:@"lb"]; //@"%.1flb"
  371. showWeight = [NSString stringWithFormat:formatStr,weight*2.2046226f];
  372. } else if (unit == 2) {
  373. showWeight = [self kg2St:weight]; //st(lb/14): **lb:**st
  374. } else if (unit == 3) {
  375. formatStr = [formatStr stringByAppendingString:@"斤"]; //@"%.1f斤"
  376. showWeight = [NSString stringWithFormat:formatStr,weight*2];
  377. }else {
  378. formatStr = [formatStr stringByAppendingString:@"kg"]; //@"%.1fkg"
  379. showWeight = [NSString stringWithFormat:formatStr,weight];
  380. }
  381. return showWeight;
  382. }
  383. - (NSString *)kg2St:(float)kgWeight {
  384. NSString *oneString = [NSString stringWithFormat:@"%d",(int)(kgWeight*2.2046226f)/14];
  385. NSString *twoString = [NSString stringWithFormat:@"%d",((int)(kgWeight*2.2046226f)%14)];
  386. return [NSString stringWithFormat:@"%@:%@st",oneString,twoString];
  387. }
  388. @end