shmMem.c 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <stdbool.h>
  6. #include <unistd.h>
  7. #include <sys/ipc.h>
  8. #include <sys/shm.h>
  9. #include "../Define/define.h"
  10. //#include "../AudiCust.h"
  11. #include "../SelectGun/SelectGun.h"
  12. #include "../common.h"
  13. #include "../Log/log.h"
  14. #include "../Config.h"
  15. #include "shmMem.h"
  16. //------------------------------------------------------------------------------
  17. static struct SysConfigAndInfo *ShmSysConfigAndInfo = NULL;
  18. //static struct SysInfoData *ShmSysInfoData = NULL;
  19. //static struct SysConfigData *ShmSysConfigData = NULL;
  20. //static struct WARNING_CODE_INFO *SysWarningInfo = NULL;
  21. static struct StatusCodeData *ShmStatusCodeData = NULL;
  22. //static struct AlarmCodeData *ShmAlarmCodeData = NULL;
  23. //static struct FaultCodeData *ShmFaultCodeData = NULL;
  24. //static struct InfoCodeData *ShmInfoCodeData = NULL;
  25. static struct PsuData *ShmPsuData = NULL;
  26. static struct CHAdeMOData *ShmCHAdeMOData = NULL;
  27. static struct GBTData *ShmGBTData = NULL;
  28. static struct CcsData *ShmCcsData = NULL;
  29. static struct PrimaryMcuData *ShmPrimaryMcuData = NULL;
  30. static struct FanModuleData *ShmFanModuleData = NULL;
  31. static struct RelayModuleData *ShmRelayModuleData = NULL;
  32. static struct LedModuleData *ShmLedModuleData = NULL;
  33. static struct OCPP16Data *ShmOCPP16Data = NULL;
  34. static struct OCPP20Data* ShmOCPP20Data = NULL;
  35. static SelectGunInfo *ShmSelectGunInfo = NULL;
  36. static DcCommonInfo *ShmDcCommonData = NULL;
  37. static struct ChargingInfoData *DcChargingData[CHAdeMO_QUANTITY + CCS_QUANTITY + GB_QUANTITY] = {NULL};
  38. static struct ChargingInfoData *AcChargingData[AC_QUANTITY] = {NULL};
  39. static GunIndexInfo gGunIndexInfo = {0};
  40. //struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
  41. //struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  42. //struct WARNING_CODE_INFO *pSysWarning = (struct WARNING_CODE_INFO *)GetShmSysWarningInfo();
  43. //struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
  44. //struct InfoCodeData *pInfoCode = (struct InfoCodeData *)GetShmInfoCodeData();
  45. //struct FaultCodeData *pFaultCode = (struct FaultCodeData *)GetShmFaultCodeData();
  46. //struct PsuData *ShmPsuData = (struct PsuData *)GetShmPsuData();
  47. //struct CHAdeMOData *ShmCHAdeMOData = (struct CHAdeMOData *)GetShmCHAdeMOData();
  48. //struct GBTData *ShmGBTData = (struct GBTData *)GetShmGBTData();
  49. //struct CcsData *ShmCcsData = (struct CcsData *)GetShmCcsData();
  50. //struct PrimaryMcuData *ShmPrimaryMcuData = (struct PrimaryMcuData *)GetShmPrimaryMcuData();
  51. //struct FanModuleData *ShmFanModuleData = (struct FanModuleData *)GetShmFanModuleData();
  52. //struct RelayModuleData *ShmRelayModuleData = (struct RelayModuleData *)GetShmRelayModuleData();
  53. //struct LedModuleData *ShmLedModuleData = (struct LedModuleData *)GetShmLedModuleData();
  54. //struct OCPP16Data *ShmOCPP16Data = (struct OCPP16Data *)GetShmOCPP16Data();
  55. //SelectGunInfo *ShmSelectGunInfo = (SelectGunInfo *)GetShmSelectGunInfo();
  56. //DcCommonInfo *ShmDcCommonData = (DcCommonInfo *)GetShmDcCommonData();
  57. //struct ChargingInfoData *pDcChargingInfo = NULL;
  58. //struct ChargingInfoData *pAcChargingInfo = NULL;
  59. //------------------------------------------------------------------------------
  60. void *GetGunIndexInfo(void)
  61. {
  62. return &gGunIndexInfo;
  63. }
  64. #if 0
  65. static int findChargingInfoData(uint8_t target, struct ChargingInfoData **chargingData)
  66. {
  67. uint8_t i = 0;
  68. for (i = 0; i < CHAdeMO_QUANTITY; i++) {
  69. if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[i].Index == target) {
  70. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[i];
  71. return PASS;
  72. }
  73. }
  74. for (i = 0; i < CCS_QUANTITY; i++) {
  75. if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[i].Index == target) {
  76. log_info("Index = %d, %d", target, ShmSysConfigAndInfo->SysInfo.CcsChargingData[i].Index);
  77. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[i];
  78. return PASS;
  79. }
  80. }
  81. for (i = 0; i < GB_QUANTITY; i++) {
  82. if (ShmSysConfigAndInfo->SysInfo.GbChargingData[i].Index == target) {
  83. chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[i];
  84. return PASS;
  85. }
  86. }
  87. return FAIL;
  88. }
  89. void MappingChargingInfoData(void) //DS60-120 add
  90. {
  91. bool isPass = true;
  92. uint8_t i = 0;
  93. while (isPass) {
  94. for (i = 0; i < 2; i++) {
  95. if (!findChargingInfoData(i, &DcChargingData[0])) {
  96. log_error("Find ChargingInfoData failed");
  97. isPass = false;
  98. break;
  99. }
  100. }
  101. sleep(1);
  102. }
  103. }
  104. #endif //0
  105. void SetAcChargingInfoData(uint8_t index, struct ChargingInfoData *chargingInfoIndex)
  106. {
  107. AcChargingData[index] = chargingInfoIndex;
  108. }
  109. void *GetAcChargingInfoData(uint8_t index)
  110. {
  111. return AcChargingData[index];
  112. }
  113. void SetDcChargingInfoData(uint8_t index, struct ChargingInfoData *chargingInfoIndex)
  114. {
  115. DcChargingData[index] = chargingInfoIndex;
  116. }
  117. void *GetDcChargingInfoData(uint8_t index)
  118. {
  119. return DcChargingData[index];
  120. }
  121. void *GetShmSysWarningInfo(void)
  122. {
  123. if (ShmSysConfigAndInfo == NULL) {
  124. return NULL;
  125. }
  126. return &ShmSysConfigAndInfo->SysWarningInfo;
  127. }
  128. void *GetShmSysConfigData(void)
  129. {
  130. if (ShmSysConfigAndInfo == NULL) {
  131. return NULL;
  132. }
  133. return &ShmSysConfigAndInfo->SysConfig;
  134. }
  135. void *GetShmSysInfoData(void)
  136. {
  137. if (ShmSysConfigAndInfo == NULL) {
  138. return NULL;
  139. }
  140. return &ShmSysConfigAndInfo->SysInfo;
  141. }
  142. void *GetShmSysConfigAndInfo(void)
  143. {
  144. if (ShmSysConfigAndInfo == NULL) {
  145. return NULL;
  146. }
  147. return ShmSysConfigAndInfo;
  148. }
  149. void *GetShmInfoCodeData(void)
  150. {
  151. if (ShmStatusCodeData == NULL) {
  152. return NULL;
  153. }
  154. return &ShmStatusCodeData->InfoCode;
  155. }
  156. void *GetShmFaultCodeData(void)
  157. {
  158. if (ShmStatusCodeData == NULL) {
  159. return NULL;
  160. }
  161. return &ShmStatusCodeData->FaultCode;
  162. }
  163. void *GetShmAlarmCodeData(void)
  164. {
  165. if (ShmStatusCodeData == NULL) {
  166. return NULL;
  167. }
  168. return &ShmStatusCodeData->AlarmCode;
  169. }
  170. void *GetShmStatusCodeData(void)
  171. {
  172. if (ShmStatusCodeData == NULL) {
  173. return NULL;
  174. }
  175. return ShmStatusCodeData;
  176. }
  177. void *GetShmPsuData(void)
  178. {
  179. if (ShmPsuData == NULL) {
  180. return NULL;
  181. }
  182. return ShmPsuData;
  183. }
  184. void *GetShmCHAdeMOData(void)
  185. {
  186. if (ShmCHAdeMOData == NULL) {
  187. return NULL;
  188. }
  189. return ShmCHAdeMOData;
  190. }
  191. void *GetShmGBTData(void)
  192. {
  193. if (ShmGBTData == NULL) {
  194. return NULL;
  195. }
  196. return ShmGBTData;
  197. }
  198. void *GetShmCcsData(void)
  199. {
  200. if (ShmCcsData == NULL) {
  201. return NULL;
  202. }
  203. return ShmCcsData;
  204. }
  205. void *GetShmPrimaryMcuData(void)
  206. {
  207. if (ShmPrimaryMcuData == NULL) {
  208. return NULL;
  209. }
  210. return ShmPrimaryMcuData;
  211. }
  212. void *GetShmFanModuleData(void)
  213. {
  214. if (ShmFanModuleData == NULL) {
  215. return NULL;
  216. }
  217. return ShmFanModuleData;
  218. }
  219. void *GetShmRelayModuleData(void)
  220. {
  221. if (ShmRelayModuleData == NULL) {
  222. return NULL;
  223. }
  224. return ShmRelayModuleData;
  225. }
  226. void *GetShmLedModuleData(void)
  227. {
  228. if (ShmLedModuleData == NULL) {
  229. return NULL;
  230. }
  231. return ShmLedModuleData;
  232. }
  233. void *GetShmOCPP16Data(void)
  234. {
  235. if (ShmOCPP16Data == NULL) {
  236. return NULL;
  237. }
  238. return ShmOCPP16Data;
  239. }
  240. void* GetShmOCPP20Data(void)
  241. {
  242. if (ShmOCPP20Data == NULL) {
  243. return NULL;
  244. }
  245. return ShmOCPP20Data;
  246. }
  247. void *GetShmSelectGunInfo(void)
  248. {
  249. if (ShmSelectGunInfo == NULL) {
  250. return NULL;
  251. }
  252. return ShmSelectGunInfo;
  253. }
  254. void *GetShmDcCommonData(void)
  255. {
  256. if (ShmDcCommonData == NULL) {
  257. return NULL;
  258. }
  259. return ShmDcCommonData;
  260. }
  261. //------------------------------------------------------------------------------
  262. static void initialGunIndexToUnUse(void)
  263. {
  264. uint8_t index = 0;
  265. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  266. for (index = 0; index < CHAdeMO_QUANTITY; index++) {
  267. pSysInfo->ChademoChargingData[index].Index = NO_DEFINE;
  268. }
  269. for (index = 0; index < CCS_QUANTITY; index++) {
  270. pSysInfo->CcsChargingData[index].Index = NO_DEFINE;
  271. }
  272. for (index = 0; index < GB_QUANTITY; index++) {
  273. pSysInfo->GbChargingData[index].Index = NO_DEFINE;
  274. }
  275. for (index = 0; index < AC_QUANTITY; index++) {
  276. pSysInfo->AcChargingData[index].Index = NO_DEFINE;
  277. }
  278. }
  279. #if 0
  280. static void getFirmwareVersion(void)
  281. {
  282. uint8_t count = 0, chademo = 0, ccs = 0, gb = 0;
  283. uint8_t index = 0;
  284. struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
  285. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  286. // Get CSU root file system version
  287. sprintf((char *)pSysInfo->CsuRootFsFwRev, fwVersion);
  288. for (index = 0; index < 3; index++) {
  289. if (pSysConfig->ModelName[7 + index] == 'J') {
  290. chademo++;
  291. count++;
  292. } else if (pSysConfig->ModelName[7 + index] == 'G') {
  293. gb++;
  294. count++;
  295. } else if (pSysConfig->ModelName[7 + index] == 'U' ||
  296. pSysConfig->ModelName[7 + index] == 'V' ||
  297. pSysConfig->ModelName[7 + index] == 'E') {
  298. ccs++;
  299. count++;
  300. }
  301. }
  302. if (count == 1) {
  303. if (chademo > 0) {
  304. pSysInfo->CsuRootFsFwRev[7] = '1';
  305. } else if (ccs > 0) {
  306. pSysInfo->CsuRootFsFwRev[7] = '2';
  307. } else if (gb > 0) {
  308. pSysInfo->CsuRootFsFwRev[7] = '3';
  309. }
  310. } else {
  311. if (chademo > 0 && ccs > 0) {
  312. pSysInfo->CsuRootFsFwRev[7] = '4';
  313. } else if (chademo > 0 && gb > 0) {
  314. pSysInfo->CsuRootFsFwRev[7] = '5';
  315. } else if (ccs > 0 && gb > 0) {
  316. pSysInfo->CsuRootFsFwRev[7] = '6';
  317. }
  318. }
  319. // Get network option from model name
  320. switch (pSysConfig->ModelName[10]) {
  321. case 'B':
  322. case 'U':
  323. //Blue tooth
  324. pSysInfo->CsuRootFsFwRev[9] = '3';
  325. break;
  326. case 'W':
  327. // WIFI
  328. pSysInfo->CsuRootFsFwRev[9] = '1';
  329. break;
  330. case 'T':
  331. // 3G/4G
  332. pSysInfo->CsuRootFsFwRev[9] = '2';
  333. break;
  334. case 'D': //DS60-120 add
  335. pSysInfo->CsuRootFsFwRev[9] = '5';
  336. break;
  337. default:
  338. // LAN
  339. pSysInfo->CsuRootFsFwRev[9] = '0';
  340. break;
  341. }
  342. // Get rating power from model name
  343. memcpy(&pSysInfo->CsuRootFsFwRev[10], &pSysConfig->ModelName[4], 0x03);
  344. // Get IEC or UL
  345. char _buf[3] = {0};
  346. memcpy(_buf, &pSysConfig->ModelName[2], 2);
  347. if (strcmp(_buf, "YE") == EQUAL || strcmp(_buf, "YC") == EQUAL) {
  348. pSysInfo->ChargerType = _CHARGER_TYPE_IEC;
  349. log_info("IEC model");
  350. } else if (strcmp(_buf, "WU") == EQUAL) {
  351. pSysInfo->ChargerType = _CHARGER_TYPE_UL;
  352. log_info("UL model");
  353. }
  354. }
  355. #endif //0
  356. void InitialShareMemoryInfo(void)
  357. {
  358. FILE *fp = NULL;
  359. char cmd[512] = {0};
  360. char buf[512] = {0};
  361. struct SysConfigData *pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
  362. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  363. struct AlarmCodeData *pAlarmCode = (struct AlarmCodeData *)GetShmAlarmCodeData();
  364. //SysConfig init
  365. sprintf((char *)pSysConfig->TelecomInterface.TelcomApn, "Internet");
  366. sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapId, " ");
  367. sprintf((char *)pSysConfig->TelecomInterface.TelcomChapPapPwd, " ");
  368. pSysConfig->TotalConnectorCount = 0;
  369. pSysConfig->AcConnectorCount = 0;
  370. memcpy(pSysInfo->CsuBootLoadFwRev,
  371. pSysConfig->CsuBootLoadFwRev,
  372. ARRAY_SIZE(pSysConfig->CsuBootLoadFwRev));
  373. strcpy((char *) pSysConfig->UserId, "");
  374. pSysConfig->QRCodeMadeMode = NO; //DS60-120 add
  375. pSysConfig->SwitchDebugFlag = NO;
  376. pSysConfig->AlwaysGfdFlag = NO;
  377. //SysInfo init
  378. pSysInfo->FactoryConfiguration = 0;
  379. pSysInfo->InputVoltageR = 0;
  380. pSysInfo->InputVoltageS = 0;
  381. pSysInfo->InputVoltageT = 0;
  382. pSysInfo->SystemFanRotaSpeed = 0;
  383. pSysInfo->PsuFanRotaSpeed = 0;
  384. pSysInfo->AuxPower5V = 0;
  385. pSysInfo->AuxPower12V = 0;
  386. pSysInfo->AuxPower24V = 0;
  387. pSysInfo->AuxPower48V = 0;
  388. sprintf((char *)pSysInfo->CsuHwRev, "REV:5.0");
  389. sprintf(cmd, "/bin/uname -r");
  390. fp = popen(cmd, "r");
  391. if (fp == NULL) {
  392. sprintf((char *)pSysInfo->CsuKernelFwRev, "Unknown version");
  393. } else {
  394. while (fgets(buf, sizeof(buf), fp) != NULL) {
  395. strcpy((char *)pSysInfo->CsuKernelFwRev, buf);
  396. }
  397. }
  398. // 雙槍 CCS + Chademo
  399. //getFirmwareVersion();
  400. //sprintf((char *) pSysInfo->CsuRootFsFwRev, fwVersion);
  401. sprintf((char *) pSysInfo->CsuPrimFwRev, " ");
  402. sprintf((char *)pSysInfo->LcmHwRev, " ");
  403. sprintf((char *)pSysInfo->LcmFwRev, " ");
  404. sprintf((char *)pSysInfo->PsuHwRev, " ");
  405. sprintf((char *)pSysInfo->PsuPrimFwRev, " ");
  406. sprintf((char *)pSysInfo->PsuSecFwRev, " ");
  407. sprintf((char *)pSysInfo->AuxPwrHwRev, " ");
  408. sprintf((char *)pSysInfo->AuxPwrFwRev, " ");
  409. sprintf((char *)pSysInfo->FanModuleHwRev, " ");
  410. sprintf((char *)pSysInfo->FanModuleFwRev, " ");
  411. sprintf((char *)pSysInfo->RelayModuleHwRev, " ");
  412. sprintf((char *)pSysInfo->RelayModuleFwRev, " ");
  413. sprintf((char *)pSysInfo->TelcomModemFwRev, " ");
  414. pSysInfo->SystemAmbientTemp = 0;
  415. pSysInfo->SystemCriticalTemp = 0;
  416. pSysInfo->PsuAmbientTemp = 0;
  417. pSysInfo->CcsConnectorTemp = 0;
  418. pSysInfo->InternetConn = 0;
  419. pSysInfo->OcppConnStatus = 0;
  420. pSysInfo->OrderCharging = NO_DEFINE;
  421. memset(pSysInfo->FanModuleFwRev, 0, ARRAY_SIZE(pSysInfo->FanModuleFwRev));
  422. memset(pSysInfo->RelayModuleFwRev, 0, ARRAY_SIZE(pSysInfo->RelayModuleFwRev));
  423. #if defined DD360Audi
  424. pSysInfo->SystemPage = _LCM_SELECT_GUN;
  425. #else
  426. pSysInfo->SystemPage = _LCM_NONE;
  427. #endif //defined DD360Audi
  428. pSysInfo->MainChargingMode = _MAIN_CHARGING_MODE_MAX;
  429. pSysInfo->ReAssignedFlag = _REASSIGNED_NONE;
  430. pSysInfo->CurGunSelectedByAc = NO_DEFINE;
  431. pSysInfo->BootingStatus = BOOTTING; //DS60-120 add
  432. //other board init
  433. ShmPrimaryMcuData->SelfTest_Comp = NO;
  434. ShmRelayModuleData->SelfTest_Comp = NO;
  435. ShmFanModuleData->SelfTest_Comp = NO;
  436. ShmLedModuleData->SelfTest_Comp = NO;
  437. ShmFanModuleData->TestFanSpeed = 0;
  438. //status code init
  439. pAlarmCode->AlarmEvents.bits.RelayboardStestFail = NO;
  440. pAlarmCode->AlarmEvents.bits.FanboardStestFail = NO;
  441. pAlarmCode->AlarmEvents.bits.PrimaryStestFail = NO;
  442. pAlarmCode->AlarmEvents.bits.LedboardStestFail = NO; //DS60-120 Add
  443. pAlarmCode->AlarmEvents.bits.ChademoboardStestFail = NO;
  444. pAlarmCode->AlarmEvents.bits.CCSboardStestFail = NO;
  445. pAlarmCode->AlarmEvents.bits.AcContactStestFail = NO;
  446. pAlarmCode->AlarmEvents.bits.PsuModuleStestFail = NO;
  447. pAlarmCode->AlarmEvents.bits.PsuDipSwitchStestFail = NO; //DS60-120 Add
  448. pAlarmCode->AlarmEvents.bits.ModelNameNoneMatchStestFail = NO;
  449. pAlarmCode->AlarmEvents.bits.PsuNoResource = NO;
  450. pAlarmCode->AlarmEvents.bits.FailToCreateShareMemory = NO;
  451. initialGunIndexToUnUse();//DS60-120 add
  452. //ShmDcCommonData->CcsVersion = _CCS_VERSION_CHECK_TAG_V015S0;
  453. //ShmDcCommonData->psuKeepCommunication = NO;
  454. //ShmDcCommonData->acContactSwitch = NO;
  455. ShmDcCommonData->ConnectErrList[0].GunErrMessage = 0;
  456. ShmDcCommonData->ConnectErrList[1].GunErrMessage = 0;
  457. ShmDcCommonData->TestTemperature = NO;
  458. //ShmDcCommonData->LcmFwVersion = 0;
  459. }
  460. int InitSelectGunShmMem(void)
  461. {
  462. int MeterSMId = FAIL;
  463. #if !defined DD360 && !defined DD360Audi && !defined DD360ComBox
  464. return;
  465. #endif //!defined DD360 && !defined DD360Audi && !defined DD360ComBox
  466. if ((MeterSMId = shmget(ShmSelectGunInfoKey, sizeof(SelectGunInfo), IPC_CREAT | 0777)) < 0) {
  467. return FAIL;
  468. } else if ((ShmSelectGunInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  469. return FAIL;
  470. }
  471. return PASS;
  472. }
  473. int InitCommonShmMem(void)
  474. {
  475. int MeterSMId = FAIL;
  476. if ((MeterSMId = shmget(ShmCommonKey, sizeof(DcCommonInfo), IPC_CREAT | 0777)) < 0) {
  477. return FAIL;
  478. } else if ((ShmDcCommonData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  479. return FAIL;
  480. }
  481. return PASS;
  482. }
  483. //int InitCSUMeterShmMem(void)
  484. //{
  485. // int MeterSMId = FAIL;
  486. //
  487. // if ((MeterSMId = shmget(ShmCsuMeterKey, sizeof(struct MeterInformation), IPC_CREAT | 0777)) < 0) {
  488. // return FAIL;
  489. // } else if ((ShmCsuMeterInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  490. // return FAIL;
  491. // }
  492. //
  493. // return PASS;
  494. //}
  495. int InitOCPPShmMem(void)
  496. {
  497. int MeterSMId = FAIL;
  498. if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), IPC_CREAT | 0777)) < 0) {
  499. log_info("Get OCPP share memory error");
  500. return FAIL;
  501. } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  502. log_info("Create OCPP share memory error");
  503. return FAIL;
  504. }
  505. return PASS;
  506. }
  507. int InitOCPP20ShmMem(void)
  508. {
  509. int MeterSMId = FAIL;
  510. if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), IPC_CREAT | 0777)) < 0) {
  511. log_info("Get OCPP20 share memory error");
  512. return FAIL;
  513. } else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void*)-1) {
  514. log_info("Create OCPP20 share memory error");
  515. return FAIL;
  516. }
  517. return PASS;
  518. }
  519. int InitLEDShmMem(void)
  520. {
  521. int MeterSMId = FAIL;
  522. if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), IPC_CREAT | 0777)) < 0) {
  523. return FAIL;
  524. } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  525. return FAIL;
  526. }
  527. return PASS;
  528. }
  529. int InitRelayShmMem(void)
  530. {
  531. int MeterSMId = FAIL;
  532. if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), IPC_CREAT | 0777)) < 0) {
  533. return FAIL;
  534. } else if ((ShmRelayModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  535. return FAIL;
  536. }
  537. return PASS;
  538. }
  539. int InitFanShmMem(void)
  540. {
  541. int MeterSMId = FAIL;
  542. if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData), IPC_CREAT | 0777)) < 0) {
  543. return FAIL;
  544. } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  545. return FAIL;
  546. }
  547. return PASS;
  548. }
  549. int InitPrimaryShmMem(void)
  550. {
  551. int MeterSMId = FAIL;
  552. if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), IPC_CREAT | 0777)) < 0) {
  553. return FAIL;
  554. } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  555. return FAIL;
  556. }
  557. return PASS;
  558. }
  559. int InitCCSShmMem(void)
  560. {
  561. int MeterSMId = FAIL;
  562. if ((MeterSMId = shmget(ShmCcsCommKey, sizeof(struct CcsData), IPC_CREAT | 0777)) < 0) {
  563. return FAIL;
  564. } else if ((ShmCcsData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  565. return FAIL;
  566. }
  567. return PASS;
  568. }
  569. int InitGBShmMem(void)
  570. {
  571. int MeterSMId = FAIL;
  572. if ((MeterSMId = shmget(ShmGBTCommKey, sizeof(struct GBTData), IPC_CREAT | 0777)) < 0) {
  573. return FAIL;
  574. } else if ((ShmGBTData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  575. return FAIL;
  576. }
  577. return PASS;
  578. }
  579. int InitCHADeMoShmMem(void)
  580. {
  581. int MeterSMId = FAIL;
  582. if ((MeterSMId = shmget(ShmCHAdeMOCommKey, sizeof(struct CHAdeMOData), IPC_CREAT | 0777)) < 0) {
  583. return FAIL;
  584. } else if ((ShmCHAdeMOData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  585. return FAIL;
  586. }
  587. return PASS;
  588. }
  589. int InitPSUDataShmMem(void)
  590. {
  591. int MeterSMId = FAIL;
  592. //creat ShmPsuData
  593. if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), IPC_CREAT | 0777)) < 0) {
  594. return FAIL;
  595. } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  596. return FAIL;
  597. }
  598. return PASS;
  599. }
  600. int InitStatusCodeShmMem(void)
  601. {
  602. int MeterSMId = FAIL;
  603. if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), IPC_CREAT | 0777)) < 0) {
  604. return FAIL;
  605. } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  606. return FAIL;
  607. }
  608. return PASS;
  609. }
  610. int InitSysConfigAndInfoShmMem(void)
  611. {
  612. int MeterSMId = FAIL;
  613. if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), IPC_CREAT | 0777)) < 0) {
  614. printf("1 InitSysConfigAndInfoShmMem");
  615. return FAIL;
  616. } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) - 1) {
  617. printf("2 InitSysConfigAndInfoShmMem");
  618. return FAIL;
  619. }
  620. return PASS;
  621. }
  622. void ClearAllShmMemParameter(void)
  623. {
  624. uint8_t i = 0;
  625. memset(ShmSysConfigAndInfo, 0, sizeof(struct SysConfigAndInfo));
  626. memset(ShmStatusCodeData, 0, sizeof(struct StatusCodeData));
  627. memset(ShmPsuData, 0, sizeof(struct PsuData));
  628. if (CHAdeMO_QUANTITY > 0) {
  629. memset(ShmCHAdeMOData, 0, sizeof(struct CHAdeMOData));
  630. }
  631. if (GB_QUANTITY > 0) {
  632. memset(ShmGBTData, 0, sizeof(struct GBTData));
  633. }
  634. if (CCS_QUANTITY > 0) {
  635. memset(ShmCcsData, 0, sizeof(struct CcsData));
  636. }
  637. memset(ShmPrimaryMcuData, 0, sizeof(struct PrimaryMcuData));
  638. memset(ShmFanModuleData, 0, sizeof(struct FanModuleData));
  639. memset(ShmRelayModuleData, 0, sizeof(struct RelayModuleData));
  640. memset(ShmLedModuleData, 0, sizeof(struct LedModuleData));
  641. //memset(ShmOCPP16Data,0,sizeof(struct OCPP16Data));
  642. //memset(ShmCsuMeterInfo, 0, sizeof(struct MeterInformation));
  643. memset(ShmDcCommonData, 0, sizeof(DcCommonInfo));
  644. #if defined DD360 || defined DD360Audi || defined DD360ComBox
  645. memset(ShmSelectGunInfo, 0, sizeof(SelectGunInfo));
  646. for (i = 0; i < ShmSysConfigAndInfo->SysConfig.TotalConnectorCount; i++) {
  647. ShmSelectGunInfo->PricesInfo[i].Balance = FAIL_BALANCE_PRICES;
  648. }
  649. #endif //defined DD360 || defined DD360Audi || defined DD360ComBox
  650. }
  651. static void setAcGunTiggerStatus(void)
  652. {
  653. struct ChargingInfoData *pAcChargingInfo = NULL;
  654. if (gGunIndexInfo.AcGunIndex == 0) {
  655. return;
  656. }
  657. pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(gGunIndexInfo.AcGunIndex);
  658. pAcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
  659. pAcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
  660. }
  661. static int findAcChargingInfoData(uint8_t gunIndex)
  662. {
  663. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  664. //acChargingData[gunIndex] = &pSysInfo->AcChargingData[0];
  665. SetAcChargingInfoData(gunIndex, &pSysInfo->AcChargingData[0]);
  666. return PASS;
  667. }
  668. static int findDcChargingInfoData(uint8_t gunIndex)
  669. {
  670. uint8_t i = 0;
  671. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  672. //printf("Chademo count = %d\n", gGunIndexInfo.ChademoIndex);
  673. for (i = 0; i < gGunIndexInfo.DcGunIndex; i++) {
  674. if (pSysInfo->ChademoChargingData[i].Index == gunIndex) {
  675. //printf("chademo index = %d, %d\n", pSysInfo->ChademoChargingData[i].Index, gunIndex);
  676. //dcChargingData[gunIndex] = &pSysInfo->ChademoChargingData[i];
  677. SetDcChargingInfoData(pSysInfo->ChademoChargingData[i].Index, &pSysInfo->ChademoChargingData[i]);
  678. return PASS;
  679. }
  680. }
  681. //printf("ccs count = %d\n", gGunIndexInfo.CcsIndex);
  682. for (i = 0; i < gGunIndexInfo.DcGunIndex; i++) {
  683. if (pSysInfo->CcsChargingData[i].Index == gunIndex) {
  684. //printf("ccs index = %d, %d\n", pSysInfo->CcsChargingData[i].Index, gunIndex);
  685. //dcChargingData[gunIndex] = (struct ChargingInfoData *)&pSysInfo->CcsChargingData[i];
  686. SetDcChargingInfoData(pSysInfo->CcsChargingData[i].Index, &pSysInfo->CcsChargingData[i]);
  687. return PASS;
  688. }
  689. }
  690. for (i = 0; i < gGunIndexInfo.DcGunIndex; i++) {
  691. if (pSysInfo->GbChargingData[i].Index == gunIndex) {
  692. //dcChargingData[gunIndex] = &pSysInfo->GbChargingData[i];
  693. SetDcChargingInfoData(pSysInfo->GbChargingData[i].Index, &pSysInfo->GbChargingData[i]);
  694. return PASS;
  695. }
  696. }
  697. return FAIL;
  698. }
  699. static bool addGunInfoByConnector(uint8_t typeValue, uint8_t slots,char *whichtask)
  700. {
  701. bool result = true;
  702. struct SysInfoData *pSysInfo = (struct SysInfoData *)GetShmSysInfoData();
  703. struct ChargingInfoData *pDcChargingInfo = NULL;
  704. struct ChargingInfoData *pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(gGunIndexInfo.AcGunIndex);
  705. struct CcsData *pCcsData = (struct CcsData *)GetShmCcsData();
  706. switch (typeValue) {
  707. // AC Gun Type -------------------------------------------------------------
  708. case '0': // none
  709. break;
  710. case '1': // IEC 62196-2 Type 1/SAE J1772 Plug
  711. break;
  712. case '2': // IEC 62196-2 Type 1/SAE J1772 Socket
  713. break;
  714. case '3': // IEC 62196-2 Type 2 Plug
  715. case '4': // IEC 62196-2 Type 2 Socket
  716. if (AC_QUANTITY > gGunIndexInfo.AcIndex) {
  717. pAcChargingInfo = (struct ChargingInfoData *)&pSysInfo->AcChargingData[gGunIndexInfo.AcIndex];
  718. // AC 固定 index
  719. pAcChargingInfo->Index = 0;
  720. pAcChargingInfo->ReservationId = -1;
  721. pAcChargingInfo->SystemStatus = S_IDLE;
  722. pAcChargingInfo->Type = _Type_AC;
  723. pAcChargingInfo->schedule.isTriggerStart = NO; //DS60-120 add
  724. pAcChargingInfo->schedule.isTriggerStop = NO; //DS60-120 add
  725. //if( strcmp(whichtask,"CSU task") == EQUAL )
  726. {
  727. gGunIndexInfo.AcIndex++;
  728. gGunIndexInfo.AcGunIndex++;
  729. pAcChargingInfo->IsAvailable = YES;
  730. }
  731. } else {
  732. result = false;
  733. }
  734. break;
  735. case '5': // GB/T AC Plug
  736. break;
  737. case '6': // GB/T AC Socket
  738. break;
  739. //DC Gun Type --------------------------------------------------------------
  740. case 'J': // CHAdeMO
  741. case 'K': // CHAdeMO 200A
  742. if (CHAdeMO_QUANTITY > gGunIndexInfo.ChademoIndex) {
  743. pDcChargingInfo = (struct ChargingInfoData *)&pSysInfo->ChademoChargingData[gGunIndexInfo.ChademoIndex];
  744. pDcChargingInfo->Index = gGunIndexInfo.DcGunIndex;
  745. pDcChargingInfo->ReservationId = -1;
  746. pDcChargingInfo->slotsIndex = slots;
  747. //pDcChargingInfo->SystemStatus = S_BOOTING;
  748. //pDcChargingInfo->SystemStatus = S_IDLE;
  749. pDcChargingInfo->Type = _Type_Chademo;
  750. pDcChargingInfo->type_index = gGunIndexInfo.ChademoIndex;
  751. setAcGunTiggerStatus();
  752. //if( strcmp(whichtask,"CSU task") == EQUAL )
  753. {
  754. pDcChargingInfo->IsAvailable = YES;
  755. gGunIndexInfo.ChademoIndex++;
  756. gGunIndexInfo.DcGunIndex++;
  757. }
  758. } else {
  759. result = false;
  760. }
  761. break;
  762. case 'T': // Rema CCS1
  763. case 'D': // Rema CCS2
  764. case 'U': // CCS1 combo
  765. case 'E': // CCS2 combo
  766. case 'V': // Liquid CCS1 combo
  767. case 'F': // Liquid CCS2 combo
  768. case 'M': // 80A CCS2
  769. case 'N': // 80A CCS1
  770. case 'P': // Phoenix CCS2 500A 水冷
  771. case 'R': // Phoenix CCS1 500A 水冷
  772. if (CCS_QUANTITY > gGunIndexInfo.CcsIndex) {
  773. pDcChargingInfo = (struct ChargingInfoData *)&pSysInfo->CcsChargingData[gGunIndexInfo.CcsIndex];
  774. pDcChargingInfo->Index = gGunIndexInfo.DcGunIndex;
  775. pDcChargingInfo->ReservationId = -1;
  776. pDcChargingInfo->slotsIndex = slots;
  777. //pDcChargingInfo->SystemStatus = S_BOOTING;
  778. pDcChargingInfo->Type = _Type_CCS_2;
  779. pDcChargingInfo->type_index = gGunIndexInfo.CcsIndex;
  780. setAcGunTiggerStatus();
  781. // 現階段預設為走 DIN70121
  782. pCcsData->CommProtocol = _CCS_COMM_V2GMessage_DIN70121;
  783. //if( strcmp(whichtask,"CSU task") == EQUAL )
  784. {
  785. pDcChargingInfo->IsAvailable = YES;
  786. gGunIndexInfo.CcsIndex++;
  787. gGunIndexInfo.DcGunIndex++;
  788. }
  789. if(typeValue == 'P')
  790. {
  791. pDcChargingInfo->PantographFlag = YES;
  792. }
  793. } else {
  794. result = false;
  795. }
  796. break;
  797. case 'G': // GBT DC
  798. if (GB_QUANTITY > gGunIndexInfo.GbIndex) {
  799. pDcChargingInfo = (struct ChargingInfoData *)&pSysInfo->GbChargingData[gGunIndexInfo.GbIndex];
  800. pDcChargingInfo->Index = gGunIndexInfo.DcGunIndex;
  801. pDcChargingInfo->ReservationId = -1;
  802. pDcChargingInfo->slotsIndex = slots;
  803. //pDcChargingInfo->SystemStatus = S_BOOTING;
  804. pDcChargingInfo->Type = _Type_GB;
  805. pDcChargingInfo->type_index = gGunIndexInfo.GbIndex;
  806. setAcGunTiggerStatus();
  807. //if( strcmp(whichtask,"CSU task") == EQUAL )
  808. {
  809. pDcChargingInfo->IsAvailable = YES;
  810. gGunIndexInfo.GbIndex++;
  811. gGunIndexInfo.DcGunIndex++;
  812. }
  813. } else {
  814. result = false;
  815. }
  816. break;
  817. //case 'D': // GBT DC x 2
  818. // break;
  819. //default:
  820. // result = false;
  821. // break;
  822. }
  823. return result;
  824. }
  825. bool MappingGunChargingInfo(char *whichTask)
  826. {
  827. bool result = true;
  828. uint8_t typeIndex = 0;
  829. uint8_t slots = 1;
  830. uint8_t gunIndex = 0;
  831. struct SysConfigData *pSysConfig = NULL;
  832. //struct ChargingInfoData *pDcChargingInfo = NULL;
  833. struct ChargingInfoData *pAcChargingInfo = NULL;
  834. if (ShmSysConfigAndInfo == NULL) {
  835. log_error("ShmSysConfigAndInfo failed");
  836. return false;
  837. }
  838. pSysConfig = (struct SysConfigData *)GetShmSysConfigData();
  839. if (strlen((char *)pSysConfig->ModelName) < 9) {
  840. log_error("Module name length < 9 get %s", (char *)pSysConfig->ModelName);
  841. return false;
  842. }
  843. ShmDcCommonData->ChillerValve.MultiChillerGun = 0;
  844. //printf("1 CheckConnectorTypeStatus\n");
  845. for (typeIndex = 7; typeIndex <= 9; typeIndex++) {
  846. if (!addGunInfoByConnector(pSysConfig->ModelName[typeIndex], slots, whichTask)) {
  847. log_error("%s add gun info failed", whichTask);
  848. return false;
  849. }
  850. //確認有幾把水冷槍
  851. if (strncmp((char *)&pSysConfig->ModelName[typeIndex], "V", 1) == 0 ||
  852. strncmp((char *)&pSysConfig->ModelName[typeIndex], "F", 1) == 0
  853. ) {
  854. ShmDcCommonData->ChillerValve.MultiChillerGun++; //水冷槍數
  855. }
  856. slots++;
  857. }
  858. if (ShmDcCommonData->ChillerValve.MultiChillerGun != 0) {
  859. ShmDcCommonData->ChillerValve.MultiChillerGun |= 0x80; //有水冷槍標記
  860. if (strncmp(whichTask, "CSU Task", 8) == EQUAL) {
  861. log_info("get chiller gun = %x, chiller gun count = %d",
  862. (ShmDcCommonData->ChillerValve.MultiChillerGun & 0x80) >> 7,
  863. ShmDcCommonData->ChillerValve.MultiChillerGun & 0x7F);
  864. }
  865. }
  866. // AC index 接在 DC 後面
  867. //if (AC_QUANTITY > 0) {
  868. if (gGunIndexInfo.AcIndex > 0) { //DS60-120 add
  869. pAcChargingInfo = (struct ChargingInfoData *)GetAcChargingInfoData(0);
  870. pAcChargingInfo->Index += gGunIndexInfo.DcGunIndex;
  871. }
  872. pSysConfig->TotalConnectorCount = gGunIndexInfo.DcGunIndex;
  873. pSysConfig->AcConnectorCount = gGunIndexInfo.AcGunIndex;
  874. if (strcmp(whichTask, "CSU Task") == 0) {
  875. log_info("DC connector Quality = %d, AC connector Quality = %d",
  876. pSysConfig->TotalConnectorCount,
  877. pSysConfig->AcConnectorCount);
  878. }
  879. for (gunIndex = 0; gunIndex < pSysConfig->TotalConnectorCount; gunIndex++) {
  880. findDcChargingInfoData(gunIndex);
  881. }
  882. findAcChargingInfoData(gunIndex);
  883. //log_info("Type 0~3 = CHAdeMO, CCS, GB, AC");
  884. if (pSysConfig->TotalConnectorCount == 0 && pSysConfig->AcConnectorCount == 0) {
  885. log_error("DC %d or AC %d connector failed",
  886. pSysConfig->TotalConnectorCount,
  887. pSysConfig->AcConnectorCount);
  888. result = false;
  889. }
  890. return result;
  891. }
  892. int CreateAllCsuShareMemory(void)
  893. {
  894. int ret = FAIL;
  895. if ((ret = InitSysConfigAndInfoShmMem()) == FAIL) {
  896. return ret;
  897. }
  898. if ((ret = InitStatusCodeShmMem()) == FAIL) {
  899. return ret;
  900. }
  901. if ((ret = InitPSUDataShmMem()) == FAIL) {
  902. return ret;
  903. }
  904. if (CHAdeMO_QUANTITY > 0) {
  905. if ((ret = InitCHADeMoShmMem()) == FAIL) {
  906. return ret;
  907. }
  908. }
  909. if (GB_QUANTITY > 0) {
  910. if ((ret = InitGBShmMem()) == FAIL) {
  911. return ret;
  912. }
  913. }
  914. //creat ShmCcsData
  915. if (CCS_QUANTITY > 0) {
  916. if ((ret = InitCCSShmMem()) == FAIL) {
  917. return ret;
  918. }
  919. }
  920. if ((ret = InitPrimaryShmMem()) == FAIL) {
  921. return ret;
  922. }
  923. if ((ret = InitFanShmMem()) == FAIL) {
  924. return ret;
  925. }
  926. if ((ret = InitRelayShmMem()) == FAIL) {
  927. return ret;
  928. }
  929. if ((ret = InitLEDShmMem()) == FAIL) {
  930. return ret;
  931. }
  932. if ((ret = InitOCPPShmMem()) == FAIL) {
  933. return ret;
  934. }
  935. if ((ret = InitOCPP20ShmMem()) == FAIL) {
  936. return ret;
  937. }
  938. if ((ret = InitSelectGunShmMem()) == FAIL) {
  939. return ret;
  940. }
  941. if ((ret = InitSelectGunShmMem()) == FAIL) {
  942. return ret;
  943. }
  944. if ((ret = InitCommonShmMem()) == FAIL) {
  945. return ret;
  946. }
  947. //ClearAllShmMemParameter();
  948. //MappingChargingInfoData();
  949. //initialShareMemoryParameter();
  950. //initialGunIndexToUnUse();
  951. sleep(1);
  952. return PASS;
  953. }