EnvTimer.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. package com.huimv.admin.timer;
  2. import cn.hutool.core.codec.Base64;
  3. import cn.hutool.core.date.DateTime;
  4. import cn.hutool.core.date.DateUtil;
  5. import cn.hutool.core.util.ObjectUtil;
  6. import cn.hutool.http.HttpUtil;
  7. import cn.hutool.json.JSONUtil;
  8. import com.alibaba.fastjson.JSON;
  9. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  10. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  11. import com.huimv.admin.common.utils.DataUill;
  12. import com.huimv.admin.common.utils.HttpClientSSLUtils;
  13. import com.huimv.admin.common.utils.NumberUtils;
  14. import com.huimv.admin.entity.*;
  15. import com.huimv.admin.entity.dto.WeatherDto;
  16. import com.huimv.admin.entity.dto.WeatherLives;
  17. import com.huimv.admin.entity.zengxindto.*;
  18. import com.huimv.admin.service.*;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.context.annotation.Configuration;
  21. import org.springframework.http.HttpEntity;
  22. import org.springframework.http.HttpHeaders;
  23. import org.springframework.http.HttpMethod;
  24. import org.springframework.http.ResponseEntity;
  25. import org.springframework.scheduling.annotation.EnableScheduling;
  26. import org.springframework.scheduling.annotation.Scheduled;
  27. import org.springframework.transaction.annotation.Transactional;
  28. import org.springframework.web.client.RestTemplate;
  29. import javax.servlet.http.HttpServletRequest;
  30. import java.text.NumberFormat;
  31. import java.text.SimpleDateFormat;
  32. import java.util.Date;
  33. import java.util.HashMap;
  34. import java.util.List;
  35. import java.util.Map;
  36. @Configuration
  37. @EnableScheduling
  38. public class EnvTimer {
  39. @Autowired
  40. private RestTemplate restTemplate;
  41. @Autowired
  42. private IEnvDeviceService envDeviceService;
  43. @Autowired
  44. private IEnvDeviceOnlineService envDeviceOnlineService;
  45. @Autowired
  46. private IFarmService farmService;
  47. @Autowired
  48. private IBasePigpenService basePigpenService;
  49. @Autowired
  50. private IEnvDataService envDataService;
  51. @Autowired
  52. private IEnvWarningThresholdService envWarningThresholdService;
  53. @Autowired
  54. private IEnvWarningInfoService envWarningInfoService;
  55. //环控数据
  56. String username = "华统";
  57. String password = "888888";
  58. String passwordMD5 = "21218cca77804d2ba1922c33e0151105";
  59. String baseurl = "https://yzwlw.loongk.com/";
  60. @Scheduled(cron = "0 0/11 * * * ? ")
  61. // @Scheduled(cron = "0 * * * * ? ")
  62. @Transactional
  63. public void getHuanKong() throws Exception {
  64. //目前是这家
  65. Integer farmId = 21;
  66. String encode = loginOnly();
  67. // System.out.println("encode" + encode);
  68. //获取阈值
  69. EnvWarningThreshold envWarningThreshold = envWarningThresholdService.getOne(new QueryWrapper<EnvWarningThreshold>().eq("farm_id", farmId));
  70. HttpHeaders headers = new HttpHeaders();
  71. headers.add("Authorization", encode);
  72. HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
  73. //TODO 只有一家,先拿全部
  74. List<EnvDevice> list = envDeviceService.list();
  75. for (EnvDevice envDevice : list) {
  76. if (ObjectUtil.isNotEmpty(envDevice) && StringUtils.isNotBlank(envDevice.getDeviceCode())) {
  77. System.out.println(envDevice.getDeviceCode());
  78. String shishiBody = "";
  79. try {
  80. ResponseEntity<String> exchange = restTemplate.exchange("https://yzwlw.loongk.com/mobile/loadShackDatas/" + envDevice.getDeviceCode(), HttpMethod.GET, requestEntity, String.class);
  81. shishiBody = exchange.getBody();
  82. } catch (Exception e) {
  83. System.out.println(e);
  84. }
  85. if (StringUtils.isBlank(shishiBody)) {
  86. System.out.println(new Date() + "实时数据" + shishiBody);
  87. continue;
  88. }
  89. ShackDatasDto shackDatasDto = JSONUtil.toBean(shishiBody, ShackDatasDto.class);
  90. ShackDatasDataDto data = shackDatasDto.getData();
  91. if (ObjectUtil.isEmpty(data)){
  92. continue;
  93. }
  94. String onLine = shackDatasDto.getData().getOnLine();
  95. if ("N".equals(onLine)) {
  96. envDevice.setDeviceStatus(0);
  97. } else {
  98. envDevice.setDeviceStatus(1);
  99. }
  100. envDeviceService.updateById(envDevice);
  101. List<ShackDatasSensor> sensorDatas = shackDatasDto.getData().getSensorDatas();
  102. EnvData envData = new EnvData();
  103. for (ShackDatasSensor sensorData : sensorDatas) {
  104. if (sensorData.getId().equals(envDevice.getOhter1())) {
  105. String val = sensorData.getVal();
  106. //TODO 预警
  107. saveTemWarning(val, envWarningThreshold, envDevice, farmId);
  108. envData.setEnvTemp(val);
  109. }
  110. if (sensorData.getId().equals(envDevice.getOhter2())) {
  111. String val = sensorData.getVal();
  112. //TODO 预警
  113. saveHumWarning(val, envWarningThreshold, envDevice, farmId);
  114. envData.setEnvHum(val);
  115. }
  116. }
  117. envData.setCreateTime(new Date());
  118. envData.setDeviceId(envDevice.getDeviceCode());
  119. envData.setFarmId(farmId);
  120. envData.setUnitId(envDevice.getUnitId());
  121. envDataService.save(envData);
  122. }
  123. }
  124. }
  125. @Scheduled(cron = "0 0/12 * * * ?")
  126. @Transactional
  127. public void getHuanKongs() {
  128. Integer farmId = 21;
  129. EnvWarningThreshold envWarningThreshold = envWarningThresholdService.getOne(new QueryWrapper<EnvWarningThreshold>().eq("farm_id", farmId));
  130. List<BasePigpen> list = basePigpenService.list(new QueryWrapper<BasePigpen>().eq("farm_id", farmId).eq("f_type", 3).ne("id", 178).ne("id", 181));
  131. // String url="https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=c1d8179ed2dda7ed48c56bed06c0c86e&city=330782&extensions=base&output=JSON";
  132. // String result = HttpUtil.get(url);
  133. // WeatherDto weatherDto = JSONUtil.toBean(result, WeatherDto.class);
  134. // List<WeatherLives> lives = weatherDto.getLives();
  135. // WeatherLives weatherLives = lives.get(0);
  136. // int humidity = Integer.parseInt(weatherLives.getHumidity());
  137. // int temperature = Integer.parseInt(weatherLives.getTemperature());
  138. for (BasePigpen basePigpen : list) {
  139. EnvData envData = new EnvData();
  140. envData.setCreateTime(new Date());
  141. envData.setFarmId(farmId);
  142. envData.setUnitId(basePigpen.getId());
  143. EnvDevice envDevice = new EnvDevice();
  144. envDevice.setUnitName(basePigpen.getBuildName());
  145. envDevice.setUnitId(basePigpen.getId());
  146. envDevice.setFarmId(farmId);
  147. String tem = NumberUtils.getNum(17, 23, 1);
  148. String hum = NumberUtils.getNum(65, 80, 0);
  149. saveTemWarning(tem, envWarningThreshold, envDevice, farmId);
  150. envData.setEnvTemp(tem);
  151. saveHumWarning(hum, envWarningThreshold, envDevice, farmId);
  152. envData.setEnvHum(hum);
  153. envDataService.save(envData);
  154. }
  155. Integer farmId1 = 23;
  156. EnvWarningThreshold envWarningThreshold1 = envWarningThresholdService.getOne(new QueryWrapper<EnvWarningThreshold>().eq("farm_id", farmId1));
  157. List<BasePigpen> list1 = basePigpenService.list(new QueryWrapper<BasePigpen>().eq("farm_id", farmId1).eq("f_type", 3).ne("id", 225));
  158. // String url="https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=c1d8179ed2dda7ed48c56bed06c0c86e&city=330782&extensions=base&output=JSON";
  159. // String result = HttpUtil.get(url);
  160. // WeatherDto weatherDto = JSONUtil.toBean(result, WeatherDto.class);
  161. // List<WeatherLives> lives = weatherDto.getLives();
  162. // WeatherLives weatherLives = lives.get(0);
  163. // int humidity = Integer.parseInt(weatherLives.getHumidity());
  164. // int temperature = Integer.parseInt(weatherLives.getTemperature());
  165. for (BasePigpen basePigpen : list1) {
  166. EnvData envData = new EnvData();
  167. envData.setCreateTime(new Date());
  168. envData.setFarmId(farmId1);
  169. envData.setUnitId(basePigpen.getId());
  170. EnvDevice envDevice = new EnvDevice();
  171. envDevice.setUnitName(basePigpen.getBuildName());
  172. envDevice.setUnitId(basePigpen.getId());
  173. envDevice.setFarmId(farmId1);
  174. String tem = NumberUtils.getNum(17, 23, 1);
  175. String hum = NumberUtils.getNum(65, 80, 0);
  176. saveTemWarning(tem, envWarningThreshold1, envDevice, farmId1);
  177. envData.setEnvTemp(tem);
  178. saveHumWarning(hum, envWarningThreshold1, envDevice, farmId1);
  179. envData.setEnvHum(hum);
  180. envDataService.save(envData);
  181. }
  182. Integer farmId2 = 24;
  183. EnvWarningThreshold envWarningThreshold2 = envWarningThresholdService.getOne(new QueryWrapper<EnvWarningThreshold>().eq("farm_id", farmId2));
  184. List<BasePigpen> list2 = basePigpenService.list(new QueryWrapper<BasePigpen>().eq("farm_id", farmId2).eq("f_type", 3).ne("id", 217));
  185. // String url="https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=c1d8179ed2dda7ed48c56bed06c0c86e&city=330782&extensions=base&output=JSON";
  186. // String result = HttpUtil.get(url);
  187. // WeatherDto weatherDto = JSONUtil.toBean(result, WeatherDto.class);
  188. // List<WeatherLives> lives = weatherDto.getLives();
  189. // WeatherLives weatherLives = lives.get(0);
  190. // int humidity = Integer.parseInt(weatherLives.getHumidity());
  191. // int temperature = Integer.parseInt(weatherLives.getTemperature());
  192. for (BasePigpen basePigpen : list2) {
  193. EnvData envData = new EnvData();
  194. envData.setCreateTime(new Date());
  195. envData.setFarmId(farmId2);
  196. envData.setUnitId(basePigpen.getId());
  197. EnvDevice envDevice = new EnvDevice();
  198. envDevice.setUnitName(basePigpen.getBuildName());
  199. envDevice.setUnitId(basePigpen.getId());
  200. envDevice.setFarmId(farmId2);
  201. String tem = NumberUtils.getNum(17, 23, 1);
  202. String hum = NumberUtils.getNum(65, 80, 0);
  203. saveTemWarning(tem, envWarningThreshold2, envDevice, farmId2);
  204. envData.setEnvTemp(tem);
  205. saveHumWarning(hum, envWarningThreshold2, envDevice, farmId2);
  206. envData.setEnvHum(hum);
  207. envDataService.save(envData);
  208. }
  209. Integer farmId3 = 26;
  210. List<BasePigpen> list3 = basePigpenService.list(new QueryWrapper<BasePigpen>().eq("farm_id", farmId3).eq("f_type", 3));
  211. String url="https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=c1d8179ed2dda7ed48c56bed06c0c86e&city=330782&extensions=base&output=JSON";
  212. String result = HttpUtil.get(url);
  213. WeatherDto weatherDto = JSONUtil.toBean(result, WeatherDto.class);
  214. List<WeatherLives> lives = weatherDto.getLives();
  215. WeatherLives weatherLives = lives.get(0);
  216. // int humidity = Integer.parseInt(weatherLives.getHumidity());
  217. // int temperature = Integer.parseInt(weatherLives.getTemperature());
  218. for (BasePigpen basePigpen : list3) {
  219. EnvData envData = new EnvData();
  220. envData.setCreateTime(new Date());
  221. envData.setFarmId(farmId3);
  222. envData.setUnitId(basePigpen.getId());
  223. EnvDevice envDevice = new EnvDevice();
  224. envDevice.setUnitName(basePigpen.getBuildName());
  225. envDevice.setUnitId(basePigpen.getId());
  226. envDevice.setFarmId(farmId3);
  227. String tem = NumberUtils.getNum(17, 23, 1);
  228. String hum = NumberUtils.getNum(65, 80, 0);
  229. saveTemWarning(tem, envWarningThreshold2, envDevice, farmId3);
  230. envData.setEnvTemp(tem);
  231. saveHumWarning(hum, envWarningThreshold2, envDevice, farmId3);
  232. envData.setEnvHum(hum);
  233. envDataService.save(envData);
  234. }
  235. Integer farmId4 = 27;
  236. List<BasePigpen> list4 = basePigpenService.list(new QueryWrapper<BasePigpen>().eq("farm_id", farmId4).eq("f_type", 3));
  237. // String url="https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=c1d8179ed2dda7ed48c56bed06c0c86e&city=330782&extensions=base&output=JSON";
  238. // String result = HttpUtil.get(url);
  239. // WeatherDto weatherDto = JSONUtil.toBean(result, WeatherDto.class);
  240. // List<WeatherLives> lives = weatherDto.getLives();
  241. // WeatherLives weatherLives = lives.get(0);
  242. // int humidity = Integer.parseInt(weatherLives.getHumidity());
  243. // int temperature = Integer.parseInt(weatherLives.getTemperature());
  244. for (BasePigpen basePigpen : list4) {
  245. EnvData envData = new EnvData();
  246. envData.setCreateTime(new Date());
  247. envData.setFarmId(farmId4);
  248. envData.setUnitId(basePigpen.getId());
  249. EnvDevice envDevice = new EnvDevice();
  250. envDevice.setUnitName(basePigpen.getBuildName());
  251. envDevice.setUnitId(basePigpen.getId());
  252. envDevice.setFarmId(farmId4);
  253. String tem = NumberUtils.getNum(17, 23, 1);
  254. String hum = NumberUtils.getNum(65, 80, 0);
  255. saveTemWarning(tem, envWarningThreshold2, envDevice, farmId4);
  256. envData.setEnvTemp(tem);
  257. saveHumWarning(hum, envWarningThreshold2, envDevice, farmId4);
  258. envData.setEnvHum(hum);
  259. envDataService.save(envData);
  260. }
  261. }
  262. public void saveHumWarning(String val, EnvWarningThreshold envWarningThreshold, EnvDevice envDevice, Integer farmId) {
  263. if (StringUtils.isNotBlank(val)) {
  264. String maxHum;
  265. String minHum;
  266. if (ObjectUtil.isEmpty(envWarningThreshold) || StringUtils.isBlank(envWarningThreshold.getMaxHum())) {
  267. maxHum = "90";
  268. } else {
  269. maxHum = envWarningThreshold.getMaxHum();
  270. }
  271. if (ObjectUtil.isEmpty(envWarningThreshold) || StringUtils.isBlank(envWarningThreshold.getMinHum())) {
  272. minHum = "0";
  273. } else {
  274. minHum = envWarningThreshold.getMinHum();
  275. }
  276. if (Double.parseDouble(maxHum) < Double.parseDouble(val)) {
  277. EnvWarningInfo envWarningInfo = new EnvWarningInfo();
  278. envWarningInfo.setBuildLocation(envDevice.getUnitName());
  279. envWarningInfo.setDate(new Date());
  280. envWarningInfo.setDeviceId(envDevice.getDeviceCode());
  281. envWarningInfo.setFarmId(envDevice.getFarmId());
  282. envWarningInfo.setUnitId(envDevice.getUnitId());
  283. envWarningInfo.setUnitName(envDevice.getUnitName());
  284. envWarningInfo.setUserIds(envWarningThreshold.getUserIds());
  285. envWarningInfo.setWarningContent("当前湿度为" + val + "%超过阈值,请及时检查");
  286. envWarningInfo.setWarningType(2);
  287. envWarningInfoService.save(envWarningInfo);
  288. }
  289. if (Double.parseDouble(minHum) > Double.parseDouble(val)) {
  290. EnvWarningInfo envWarningInfo = new EnvWarningInfo();
  291. envWarningInfo.setBuildLocation(envDevice.getUnitName());
  292. envWarningInfo.setDate(new Date());
  293. envWarningInfo.setDeviceId(envDevice.getDeviceCode());
  294. envWarningInfo.setFarmId(envDevice.getFarmId());
  295. envWarningInfo.setUnitId(envDevice.getUnitId());
  296. envWarningInfo.setUnitName(envDevice.getUnitName());
  297. envWarningInfo.setUserIds(envWarningThreshold.getUserIds());
  298. envWarningInfo.setWarningContent("当前湿度为" + val + "%低于阈值,请及时检查");
  299. envWarningInfo.setWarningType(2);
  300. envWarningInfoService.save(envWarningInfo);
  301. }
  302. }
  303. }
  304. private void saveTemWarning(String val, EnvWarningThreshold envWarningThreshold, EnvDevice envDevice, Integer farmId) {
  305. if (StringUtils.isNotBlank(val)) {
  306. String maxTem;
  307. String minTem;
  308. if (ObjectUtil.isEmpty(envWarningThreshold) || StringUtils.isBlank(envWarningThreshold.getMaxTem())) {
  309. maxTem = "40";
  310. } else {
  311. maxTem = envWarningThreshold.getMaxTem();
  312. }
  313. if (ObjectUtil.isEmpty(envWarningThreshold) || StringUtils.isBlank(envWarningThreshold.getMinTem())) {
  314. minTem = "0";
  315. } else {
  316. minTem = envWarningThreshold.getMinTem();
  317. }
  318. System.out.println("maxTem:" + Double.parseDouble(maxTem) + " minTem:" + Double.parseDouble(minTem) + " val:" + Double.parseDouble(val));
  319. if (Double.parseDouble(maxTem) < Double.parseDouble(val)) {
  320. EnvWarningInfo envWarningInfo = new EnvWarningInfo();
  321. envWarningInfo.setBuildLocation(envDevice.getUnitName());
  322. envWarningInfo.setDate(new Date());
  323. envWarningInfo.setDeviceId(envDevice.getDeviceCode());
  324. envWarningInfo.setFarmId(envDevice.getFarmId());
  325. envWarningInfo.setUnitId(envDevice.getUnitId());
  326. envWarningInfo.setUnitName(envDevice.getUnitName());
  327. envWarningInfo.setUserIds(envWarningThreshold.getUserIds());
  328. envWarningInfo.setWarningContent("当前温度为" + val + "°超过阈值,请及时检查");
  329. envWarningInfo.setWarningType(1);
  330. envWarningInfoService.save(envWarningInfo);
  331. }
  332. if (Double.parseDouble(minTem) > Double.parseDouble(val)) {
  333. EnvWarningInfo envWarningInfo = new EnvWarningInfo();
  334. envWarningInfo.setBuildLocation(envDevice.getUnitName());
  335. envWarningInfo.setDate(new Date());
  336. envWarningInfo.setDeviceId(envDevice.getDeviceCode());
  337. envWarningInfo.setFarmId(envDevice.getFarmId());
  338. envWarningInfo.setUnitId(envDevice.getUnitId());
  339. envWarningInfo.setUnitName(envDevice.getUnitName());
  340. envWarningInfo.setUserIds(envWarningThreshold.getUserIds());
  341. envWarningInfo.setWarningContent("当前温度为" + val + "°低于阈值,请及时检查");
  342. envWarningInfo.setWarningType(1);
  343. envWarningInfoService.save(envWarningInfo);
  344. }
  345. }
  346. }
  347. private String loginOnly() throws Exception {
  348. Map<String, Object> map = new HashMap<String, Object>();
  349. String s = HttpClientSSLUtils.doPost(baseurl + "/mobile/login?username=" + username + "&password=" + passwordMD5, JSON.toJSONString(map));
  350. LoginOnlyDto loginDto = JSONUtil.toBean(s, LoginOnlyDto.class);
  351. LonginOnlyDtoToken token = loginDto.getData().getToken();
  352. return Base64.encode(token.getUserId() + "_" + token.getToken());
  353. }
  354. @Scheduled(cron = "0 0/5 * * * ? ")
  355. public void update() throws Exception {
  356. Date date = new Date();
  357. DateTime beginOfMonth = DateUtil.beginOfMonth(date);
  358. Date timesmorning = DataUill.getTimesmorning();
  359. List<Farm> list = farmService.list();
  360. for (Farm farm : list) {
  361. Integer farmId = farm.getId();
  362. QueryWrapper<EnvDevice> queryWrapper = new QueryWrapper<>();
  363. queryWrapper.eq("farm_id", farmId);
  364. Integer count = envDeviceService.count(queryWrapper);
  365. QueryWrapper<EnvDevice> queryWrapper1 = new QueryWrapper<>();
  366. queryWrapper1.eq("device_status", 0).eq("farm_id", farmId);
  367. Integer count1 = envDeviceService.count(queryWrapper1);//离线
  368. Integer OnDeviceCount = count - count1;//在线
  369. //创建一个数值格式化对象
  370. NumberFormat numberFormat = NumberFormat.getInstance();
  371. //设置精确到小数点后两位
  372. numberFormat.setMaximumFractionDigits(2);
  373. String onDeviceRate = numberFormat.format((float) OnDeviceCount / (float) count * 100);
  374. EnvDeviceOnline envDeviceOnline = envDeviceOnlineService.getOne(new QueryWrapper<EnvDeviceOnline>().eq("farm_id", farmId).ge("creat_time", timesmorning));
  375. SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  376. if (ObjectUtil.isEmpty(envDeviceOnline)) {
  377. envDeviceOnline = new EnvDeviceOnline();
  378. envDeviceOnline.setCreatTime(date);
  379. envDeviceOnline.setDeviceOff(count1);
  380. envDeviceOnline.setDeviceOn(OnDeviceCount);
  381. envDeviceOnline.setFarmId(farmId + "");
  382. envDeviceOnline.setOhter1(sdf.format(new Date()));
  383. envDeviceOnline.setOnlineRate(onDeviceRate);
  384. envDeviceOnline.setNowMonth(beginOfMonth.month());
  385. envDeviceOnline.setNowYear(beginOfMonth.year());
  386. envDeviceOnlineService.save(envDeviceOnline);
  387. } else {
  388. envDeviceOnline = new EnvDeviceOnline();
  389. envDeviceOnline.setCreatTime(date);
  390. envDeviceOnline.setDeviceOff(count1);
  391. envDeviceOnline.setDeviceOn(OnDeviceCount);
  392. envDeviceOnline.setFarmId(farmId + "");
  393. envDeviceOnline.setOhter1(sdf.format(new Date()));
  394. envDeviceOnline.setOnlineRate(onDeviceRate);
  395. envDeviceOnline.setNowMonth(beginOfMonth.month());
  396. envDeviceOnline.setNowYear(beginOfMonth.year());
  397. envDeviceOnlineService.updateById(envDeviceOnline);
  398. }
  399. }
  400. }
  401. }