#include "Module_LcmContro.h" //================================= // Common routine //================================= char* getTimeString(void) { char *result=malloc(21); time_t timep; struct tm *p; time(&timep); p=gmtime(&timep); sprintf(result, "[%04d-%02d-%02d %02d:%02d:%02d]", (1900+p->tm_year), (1+p->tm_mon), p->tm_mday, p->tm_hour, p->tm_hour, p->tm_sec); return result; } //========================================== // Init all share memory //========================================== int InitShareMemory() { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmSysConfigAndInfo NG\n"); #endif result = FAIL; } else {} //creat ShmStatusCodeData if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { #ifdef SystemLogMessage DEBUG_ERROR("shmget ShmStatusCodeData NG\n"); #endif result = FAIL; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage DEBUG_ERROR("shmat ShmStatusCodeData NG\n"); #endif result = FAIL; } else {} return result; } //========================================== // Open and Close RS232 and R/W //========================================== int CreateCommunicationLcmPort() { int fd; struct termios tios; fd = open(pPortName, O_RDWR); if (fd <= 0) { #ifdef SystemLogMessage DEBUG_ERROR("open /dev/ttyS3 NG \n"); #endif return -1; } ioctl(fd, TCGETS, &tios); tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD; tios.c_lflag = 0; tios.c_iflag = 0; tios.c_oflag = 0; tios.c_cc[VMIN] = 0; tios.c_cc[VTIME] = (unsigned char) 5; tios.c_lflag = 0; tcflush(fd, TCIFLUSH); ioctl(fd, TCSETS, &tios); return fd; } void CloseCommunicationLcmPort() { close(_port); } void WriteCmdToLcm(byte *cmd, byte cmdLen) { int len = write(_port, cmd, cmdLen); if(len >= sizeof(cmd)) { //printf("Write cmd to LCM successfully. \n"); } } void ReadMsgFromLcm(byte *msg, byte readLen) { read(_port, msg, readLen); if(*msg == CMD_TITLE_1 && *(msg + 1) == CMD_TITLE_2) { if(*(msg + 3) == CMD_WRITE) { switch (*(msg + 4)) { case CMD_REGISTER: { // 頁面 _currentPage = (unsigned short) (*(msg + 6) << 8) + (unsigned short) *(msg + 7); } break; } } else if (*(msg + 3) == CMD_MULTI_READ) { // switch ((unsigned short) (*(msg + 4) << 8) + (unsigned short) *(msg + 5)) // { // case BUTTON_GUN_INDEX: // { // // 當前選的槍號 // _curGunIndex = (*(msg + 8)); // } // break; // } } } // for (byte idx = 0; idx < len; idx++) // printf("[system_command]-RX: %X\n", *(msg + idx)); } //================================================ // Function //================================================ void ChangeToOtherPage(short newPage) { byte cmd[7]; memset(cmd, 0x00, sizeof(cmd)); cmd[0] = CMD_TITLE_1; cmd[1] = CMD_TITLE_2; cmd[2] = 0x02 + sizeof(newPage); cmd[3] = CMD_READ; cmd[4] = CMD_REGISTER; cmd[5] = newPage >> 8; cmd[6] = newPage & 0x00FF; WriteCmdToLcm(cmd, ARRAY_SIZE(cmd)); usleep(100000); } void ChangeBackLight(bool islight) { byte value = 0x01; if (islight) { value = 0x20; } byte cmd[7]; memset(cmd, 0x00, sizeof(cmd)); cmd[0] = CMD_TITLE_1; cmd[1] = CMD_TITLE_2; cmd[2] = 0x03; cmd[3] = CMD_READ; cmd[4] = CMD_BACKLIGHT; cmd[5] = value; WriteCmdToLcm(cmd, ARRAY_SIZE(cmd)); usleep(100000); } void GetCurrentPage() { byte cmd[6]; memset(cmd, 0x00, sizeof(cmd)); byte msg[8]; memset(msg, 0x00, sizeof(msg)); cmd[0] = CMD_TITLE_1; cmd[1] = CMD_TITLE_2; cmd[2] = 0x03; // 底下總長度 cmd[3] = CMD_WRITE; cmd[4] = CMD_REGISTER; cmd[5] = 0x02; WriteCmdToLcm(cmd, ARRAY_SIZE(cmd)); usleep(100000); ReadMsgFromLcm(msg, ARRAY_SIZE(msg)); } void DisplayValueToLcm(short address, byte *data, byte len) { byte cmd[256]; memset(cmd, 0x00, sizeof(cmd)); cmd[0] = CMD_TITLE_1; cmd[1] = CMD_TITLE_2; cmd[2] = 0x03 + len; cmd[3] = CMD_MULTI_WRITE; cmd[4] = address >> 8; cmd[5] = address & 0x00FF; for(byte count = 0; count < len; count++) { cmd[6 + count] = *(data + count); } WriteCmdToLcm(cmd, cmd[2] + 3); } void ChangeDisplay2Value(short address, short value) { byte data[2]; data[0] = value >> 8; data[1] = value & 0x00FF; DisplayValueToLcm(address, data, sizeof(data)); } void GetBtnStatus(short address, byte len) { byte cmd[8]; memset(cmd, 0x00, sizeof(cmd)); byte msg[8]; memset(msg, 0x00, sizeof(msg)); cmd[0] = CMD_TITLE_1; cmd[1] = CMD_TITLE_2; cmd[2] = 0x03 + len; cmd[3] = CMD_MULTI_READ; cmd[4] = address >> 8; cmd[5] = address & 0x00FF; cmd[6] = 0x00 + len; WriteCmdToLcm(cmd, cmd[2] + 3); usleep(100000); ReadMsgFromLcm(msg, (len * 2) + sizeof(msg)); } //================================================ // Warning process //================================================ void string2ByteArray(unsigned char *input, byte *output) { int loop; int i; loop = 0; i = 0; while(input[loop] != '\0') { output[i++] = input[loop++]; } output[loop] = '\0'; } void ChangeWarningFunc() { byte cmd[7]; byte i = 0; //printf("ChangeWarningFunc \n"); // 最多一次五筆 //printf("LCM PageIndex = %d \n", ShmSysConfigAndInfo->SysWarningInfo.PageIndex); //printf("WarningCount = %d \n", ShmSysConfigAndInfo->SysWarningInfo.WarningCount); for(i = 0; (i + ShmSysConfigAndInfo->SysWarningInfo.PageIndex * 5) < ShmSysConfigAndInfo->SysWarningInfo.WarningCount; i++) { memset(cmd, 0x00, sizeof(cmd)); if(i >= 5) { break; } //error code string2ByteArray(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[i + ShmSysConfigAndInfo->SysWarningInfo.PageIndex * 5][0], cmd); DisplayValueToLcm(0x0010 + (i * 6), cmd, sizeof(cmd)); //警告標示 memset(cmd, 0x00, sizeof(cmd)); cmd[0] = 0x00; cmd[1] = 0x01; DisplayValueToLcm(0x0002 + (i * 2), cmd, 2); } memset(cmd, 0x00, sizeof(cmd)); for(; i < 5; i++) { DisplayValueToLcm(0x0010 + (i * 6), cmd, sizeof(cmd)); DisplayValueToLcm(0x0002 + (i * 2), cmd, 2); } } //================================================ // QR Code process //================================================ void ChangeQrCode_Idle(char *input) { int len = strlen(input); byte cmd[len]; int loop = 0; int i = 0; while(input[loop] != '\0') { cmd[i++] = input[loop++]; } DisplayValueToLcm(__qr_code, cmd, len); } void ChangeQrCode_Charge(char *input) { int len = strlen(input); byte cmd[len]; int loop = 0; int i = 0; while(input[loop] != '\0') { cmd[i++] = input[loop++]; } DisplayValueToLcm(__qr_code_pre, cmd, len); } //================================================ // Change current page //================================================ void ChangeCurPage() { if (_currentPage != ShmSysConfigAndInfo->SysInfo.PageIndex) { printf("Old page = %d, New page = %d \n", _currentPage, ShmSysConfigAndInfo->SysInfo.PageIndex); _currentPage = ShmSysConfigAndInfo->SysInfo.PageIndex; ChangeToOtherPage(_currentPage); gettimeofday(&_ani_time, NULL); } } //================================================ // Main process //================================================ byte demoCount = 0; void DemoFunction() { if (demoCount == 0) { ShmSysConfigAndInfo->SysWarningInfo.WarningCount = 6; memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[0][0], "000001", 7); memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[1][0], "000002", 7); memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[2][0], "000003", 7); memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[3][0], "000004", 7); memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[4][0], "000005", 7); memcpy(&ShmSysConfigAndInfo->SysWarningInfo.WarningCode[5][0], "000006", 7); } else { if (demoCount == 20) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_IDLE; } else if (demoCount == 80) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_AUTHORIZING; } else if (demoCount == 100) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_AUTHORIZ_COMP; } else if (demoCount == 120) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_AUTHORIZ_FAIL; } else if (demoCount == 140) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_PRE_CHARGE; } else if (demoCount == 180) { ShmSysConfigAndInfo->SysInfo.PageIndex = _LCM_CHARGING; } } if (demoCount < 180) demoCount++; } //================================================ // Main process //================================================ bool FindChargingInfoData(byte target, struct ChargingInfoData **_chargingData) { for (byte index = 0; index < CHAdeMO_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index].Index == target) { _chargingData[target] = &ShmSysConfigAndInfo->SysInfo.ChademoChargingData[index]; return true; } } for (byte index = 0; index < CCS_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.CcsChargingData[index].Index == target) { _chargingData[target] = &ShmSysConfigAndInfo->SysInfo.CcsChargingData[index]; return true; } } for (byte index = 0; index < GB_QUANTITY; index++) { if (ShmSysConfigAndInfo->SysInfo.GbChargingData[index].Index == target) { _chargingData[target] = &ShmSysConfigAndInfo->SysInfo.GbChargingData[index]; return true; } } return false; } void ChangeBattMapAndValue(short page, int soc, byte isNext) { // srand(time(NULL)); // int min = 10; // int max = 90; // soc = rand() % (max - min + 1) + min; if (page == _LCM_CHARGING) { if (isNext) { if (soc < 20) ChangeDisplay2Value(__batt_map, _battery_cap_20); else if (soc >= 20 && soc < 40) ChangeDisplay2Value(__batt_map, _battery_cap_20); else if (soc >= 40 && soc < 60) ChangeDisplay2Value(__batt_map, _battery_cap_40); else if (soc >= 60 && soc < 80) ChangeDisplay2Value(__batt_map, _battery_cap_60); else if (soc >= 80 && soc <= 100) ChangeDisplay2Value(__batt_map, _battery_cap_80); } else { if (soc < 20) ChangeDisplay2Value(__batt_map, _battery_cap_20); else if (soc >= 20 && soc < 40) ChangeDisplay2Value(__batt_map, _battery_cap_40); else if (soc >= 40 && soc < 60) ChangeDisplay2Value(__batt_map, _battery_cap_60); else if (soc >= 60 && soc < 80) ChangeDisplay2Value(__batt_map, _battery_cap_80); else if (soc >= 80 && soc <= 100) ChangeDisplay2Value(__batt_map, _battery_cap_100); } } else if (page == _LCM_COMPLETE) { if (soc < 20) ChangeDisplay2Value(__batt_map, _battery_soc_20); else if (soc >= 20 && soc < 40) ChangeDisplay2Value(__batt_map, _battery_soc_40); else if (soc >= 40 && soc < 60) ChangeDisplay2Value(__batt_map, _battery_soc_60); else if (soc >= 60 && soc < 80) ChangeDisplay2Value(__batt_map, _battery_soc_80); else if (soc >= 80 && soc <= 100) ChangeDisplay2Value(__batt_map, _battery_soc_100); } byte cmd[4]; byte value[4]; memset(cmd, 0x00, sizeof(cmd)); sprintf((char *)value, "%d%%", soc); string2ByteArray(value, cmd); DisplayValueToLcm(__soc_value_charging, cmd, sizeof(cmd)); } void ChangeRemainTime(int sec) { int h, m, s; byte cmd[10]; byte value[10]; memset(cmd, 0x00, sizeof(cmd)); // srand(time(NULL)); // int min = 0; // int max = 65536; // sec = rand() % (max - min + 1) + min; h = (sec / 3600); m = (sec - (3600 * h)) / 60; s = (sec - (3600 * h) - (m * 60)); sprintf((char *)value, "%02d:%02d:%02d", h, m, s); string2ByteArray(value, cmd); DisplayValueToLcm(__remain_time_tx, cmd, sizeof(cmd)); } void ChangeChargingPowerValue(float pow) { byte cmd[10]; byte value[10]; memset(cmd, 0x00, sizeof(cmd)); // float min = 0.0; // float max = 50; // pow = (max - min) * rand() / (RAND_MAX + 1.0) + min; sprintf((char *) value, "%.1f kW", pow); string2ByteArray(value, cmd); DisplayValueToLcm(__output_eng_tx, cmd, sizeof(cmd)); } void ChangeChargingEnergyValue(float energy) { byte cmd[10]; byte value[10]; memset(cmd, 0x00, sizeof(cmd)); sprintf((char *) value, "%.1f kWh", energy); string2ByteArray(value, cmd); DisplayValueToLcm(__total_out_eng_tx, cmd, sizeof(cmd)); } void RefreshPageAnimation() { int time = GetTimeoutValue(_ani_time) / 1000; switch(_currentPage) { case _LCM_IDLE: { if (time >= 0 && time < 3000) { ChangeToOtherPage(_currentPage); } else if (time >= 3000 && time < 6000) { ChangeToOtherPage(_currentPage + 1); } else if (time >= 6000 && time < 9000) { ChangeToOtherPage(_currentPage + 2); } else if (time >= 9000) { ChangeToOtherPage(_currentPage); gettimeofday(&_ani_time, NULL); } } break; case _LCM_WAIT_FOR_PLUG: { if (time >= 0 && time < 1000) { ChangeDisplay2Value(__plug_in_arrow, _arrow_dark); } else if (time >= 1000 && time < 2000) { ChangeDisplay2Value(__plug_in_arrow, _arrow_light); } else if (time >= 2000) { ChangeDisplay2Value(__plug_in_arrow, _arrow_dark); gettimeofday(&_ani_time, NULL); } } break; case _LCM_PRE_CHARGE: case _LCM_CHARGING: case _LCM_COMPLETE: { if (_currentPage == _LCM_PRE_CHARGE) { if (time >= 0 && time < 1000) { ChangeDisplay2Value(__conn_line, _conn_map1); } else if (time >= 1000 && time < 2000) { ChangeDisplay2Value(__conn_line, _conn_map2); } else if (time >= 2000) { ChangeDisplay2Value(__conn_line, _conn_map1); gettimeofday(&_ani_time, NULL); } } else if (_currentPage == _LCM_CHARGING) { if (time >= 0 && time < 1000) { ChangeDisplay2Value(__conn_line_chag, _charging_map1); } else if (time >= 1000 && time < 2000) { ChangeDisplay2Value(__conn_line_chag, _charging_map2); } if ((time >= 0 && time < 500) || (time >= 1000 && time < 1500)) { ChangeBattMapAndValue(_LCM_CHARGING, _chargingInfoData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc, 0); } else if ((time >= 500 && time < 1000) || (time >= 1500 && time < 2000)) { ChangeBattMapAndValue(_LCM_CHARGING, _chargingInfoData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc, 1); } if (time >= 2000) { ChangeDisplay2Value(__conn_line_chag, _charging_map1); ChangeBattMapAndValue(_LCM_CHARGING, _chargingInfoData[ShmSysConfigAndInfo->SysInfo.CurGunSelected]->EvBatterySoc, 0); gettimeofday(&_ani_time, NULL); } } else if (_currentPage == _LCM_COMPLETE) { ChangeDisplay2Value(__conn_line_comp, _complete_map); } ChangeDisplay2Value(__side_top, _disappear); ChangeDisplay2Value(__side_down, _disappear); ChangeDisplay2Value(__qr_code_pre, _disappear); } break; } } void RefreshConnStatus() { // Wifi priority is higher than Ethernet if (ShmSysConfigAndInfo->SysConfig.AthInterface.WifiNetworkConn == 0x01) { if (!_wifi_conn_status) { _wifi_conn_status = true; ChangeDisplay2Value(__wifi_status, _wifi_connect); ChangeDisplay2Value(__ethernet_status, _disappear); } } else { if(_wifi_conn_status) { _wifi_conn_status = false; ChangeDisplay2Value(__wifi_status, _disappear); } } if (!_wifi_conn_status) { if (ShmSysConfigAndInfo->SysConfig.TelecomInterface.TelcomNetworkConn == 0x01) { if(!_net_conn_status) { _net_conn_status = true; ChangeDisplay2Value(__ethernet_status, _ethernet_connect); } } else { if(_net_conn_status) { _net_conn_status = false; ChangeDisplay2Value(__ethernet_status, _ethernet_disconnect); } } } // 連線到後台 } void ProcessPageInfo() { switch(_currentPage) { case _LCM_IDLE: { // QR Code 處理 ChangeQrCode_Idle("http://google.com.tw"); } break; case _LCM_PRE_CHARGE: case _LCM_CHARGING: case _LCM_COMPLETE: { // gun type and charging info for(byte i = 0; i < _totalCount; i++) { switch(_chargingInfoData[i]->Type) { case _Type_Chademo: { if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i) { ChangeDisplay2Value(__gun_type_index + (i * 2), _chademo_light); } else { ChangeDisplay2Value(__gun_type_index + (i * 2), _chademo_dark); } } break; case _Type_CCS: { if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i) { ChangeDisplay2Value(__gun_type_index + (i * 2), _ccs_light); } else { ChangeDisplay2Value(__gun_type_index + (i * 2), _ccs_dark); } } break; } if (_currentPage == _LCM_PRE_CHARGE) { if (!isAbnormalStopFlag) ChangeDisplay2Value(__ret_home_btn, _back_home_btn); } else if (_currentPage == _LCM_CHARGING) { if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i) { ChangeRemainTime(_chargingInfoData[i]->PresentChargedDuration); ChangeChargingPowerValue(_chargingInfoData[i]->PresentChargingPower); ChangeChargingEnergyValue(_chargingInfoData[i]->PresentChargedEnergy); } if (!isAbnormalStopFlag) { if (strlen((char *)_chargingInfoData[i]->CardNumber) > 0) ChangeDisplay2Value(__stop_charging_btn, _stop_charging_rfid_btn); else ChangeDisplay2Value(__stop_charging_btn, _stop_charging_btn); } } else if (_currentPage == _LCM_COMPLETE) { if (ShmSysConfigAndInfo->SysInfo.CurGunSelected == i) { ChangeBattMapAndValue(_LCM_COMPLETE, _chargingInfoData[i]->EvBatterySoc, 0); ChangeRemainTime(_chargingInfoData[i]->RemainChargingDuration); ChangeChargingPowerValue(_chargingInfoData[i]->PresentChargingPower); } ChangeDisplay2Value(__ret_home_btn, _disappear); } } // 選槍功能 ChangeDisplay2Value(__sel_gun_btn, _disappear); } break; } } void Initialization() { strcpy((char *)ShmSysConfigAndInfo->SysInfo.LcmHwRev, moduleName); bool isPass = false; while(!isPass) { isPass = true; for (byte _index = 0; _index < _totalCount; _index++) { if (!FindChargingInfoData(_index, &_chargingInfoData[0])) { DEBUG_ERROR("EvComm (main) : FindChargingInfoData false \n"); isPass = false; break; } } } ChangeDisplay2Value(__gun_type_index, _disappear); ChangeDisplay2Value(__gun_type_index + 2, _disappear); } void DisplayStopCode() { byte cmd[7]; memset(cmd, 0x00, sizeof(cmd)); if (strlen((char *)ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[ShmSysConfigAndInfo->SysInfo.CurGunSelected]) > 0) { isAbnormalStopFlag = true; ChangeDisplay2Value(__sel_gun_btn, _disappear); ChangeDisplay2Value(__ret_home_btn, _disappear); ChangeDisplay2Value(__stop_charging_btn, _disappear); string2ByteArray(&ShmSysConfigAndInfo->SysStopChargingAlarmCode.StopCode[ShmSysConfigAndInfo->SysInfo.CurGunSelected][0], cmd); } else isAbnormalStopFlag = false; DisplayValueToLcm(__charging_proc_stop_tx, cmd, sizeof(cmd)); } int main(void) { if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage DEBUG_ERROR("InitShareMemory NG\n"); #endif if (ShmStatusCodeData != NULL) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory = 1; } sleep(5); return 0; } _port = CreateCommunicationLcmPort(); byte changeWarningPriority = 0; byte curWarningCount = 255; ChangeBackLight(true); Initialization(); //ShmSysConfigAndInfo->SysInfo.PageIndex = S_IDLE; while(_port != -1) { //DemoFunction(); // Warning 處理 DisplayStopCode(); if(curWarningCount != ShmSysConfigAndInfo->SysWarningInfo.WarningCount) { changeWarningPriority = 0; ShmSysConfigAndInfo->SysWarningInfo.PageIndex = 0; curWarningCount = ShmSysConfigAndInfo->SysWarningInfo.WarningCount; ChangeWarningFunc(); } else if (ShmSysConfigAndInfo->SysWarningInfo.WarningCount > 5 && changeWarningPriority == 0) { // 當有兩頁 Warning 則每隔三秒改變一次 if(ShmSysConfigAndInfo->SysWarningInfo.PageIndex == 0) ShmSysConfigAndInfo->SysWarningInfo.PageIndex = 1; else ShmSysConfigAndInfo->SysWarningInfo.PageIndex = 0; ChangeWarningFunc(); } // 頁面資訊處理 ProcessPageInfo(); // 網路 - wifi - 連線訊號處理 RefreshConnStatus(); // 換頁處理 ChangeCurPage(); RefreshPageAnimation(); changeWarningPriority >= 30 ? changeWarningPriority = 0 : changeWarningPriority++; usleep(100000); } CloseCommunicationLcmPort(); return FAIL; }