/* * * NOTES: * * REVISIONS: * ker02DEC92: Initial breakout of sensor classes into indiv files * ker04DEC92: Initial Filling in of Member Functions * SjA11Dec92: Validate method now returns ErrNO_ERROR rather than VALID. * pcy17Dec92: Now I do StateSensor::Validate before doing my own. * pcy16Feb93: No longer need to register for UPS_STATE * pcy16Feb93: Get transfer cause and ignore if self test * ajr22Feb93: included utils.h * jod05Apr93: Added changes for Deep Discharge * cad09Sep93: Fix for lights test causing events * pcy09Sep93: Check LINE_AVAILABILITY to make sure line is bad * pcy10Sep93: Hopefully this works now * pcy18Sep93: Cleaned up line condition handling * pcy20Sep93: handle line fails during tests and sim pwr fail * pcy12Oct93: 2 ABNORMALS to cause a line bad (fixes LF during cal) * pcy13Apr94: Use automatic variables decrease dynamic mem allocation * djs16Mar95: changed upsstate.h to sysstate.h * cgm10Apr96: Destructor should unregister */ #define INCL_BASE #define INCL_DOS #define INCL_NOPM #include "cdefine.h" extern "C" { #if (C_OS & C_OS2) #include #endif #include #include #include #include } #include "ulinecon.h" #include "comctrl.h" #include "device.h" #include "event.h" #include "utils.h" #include "sysstate.h" #include "timerman.h" #define QCOMMAND 0 #define NINECOMMAND 1 UtilityLineConditionSensor :: UtilityLineConditionSensor(PDevice aParent, PCommController aCommController) : StateSensor(aParent, aCommController, UTILITY_LINE_CONDITION), theInformationSource(0), theLineFailCount(0), theUpsState(0) { storeState(LINE_GOOD); theCommController->RegisterEvent(UTILITY_LINE_CONDITION, this); theDevice->RegisterEvent(BATTERY_CALIBRATION_CONDITION, this); theDevice->RegisterEvent(SIMULATE_POWER_FAIL, this); theDevice->RegisterEvent(SELF_TEST_STATE, this); } INT UtilityLineConditionSensor::Update(PEvent anEvent) { INT err = ErrNO_ERROR; INT aCode = anEvent->GetCode(); PCHAR aValue = anEvent->GetValue(); switch(aCode) { case BATTERY_CALIBRATION_CONDITION: switch(atoi(aValue)) { case BATTERY_CALIBRATION_IN_PROGRESS: theCommController->UnregisterEvent(UTILITY_LINE_CONDITION, this); theCommController->RegisterEvent(LINE_CONDITION_TEST, this); theInformationSource = NINECOMMAND; break; case NO_BATTERY_CALIBRATION: case NO_BATTERY_CALIBRATION_IN_PROGRESS: case BATTERY_CALIBRATION_CANCELLED: if (theInformationSource == NINECOMMAND) { theCommController->UnregisterEvent(LINE_CONDITION_TEST, this); theCommController->RegisterEvent(UTILITY_LINE_CONDITION, this); theInformationSource = QCOMMAND; } break; } break; case LINE_CONDITION_TEST: // // Convert the event to a UTILITY_LINE_CONDITION event and // send it to myself // switch(atoi(aValue)) { case ABNORMAL_CONDITION: { // // Only after the second successive abnormal condition should // we bother with this. This is so we ignore ABNORMAL_COND // events at the start of deep discharge // if(theLineFailCount > 0) { CHAR lbtmp[31]; sprintf(lbtmp, "%d", LINE_BAD); if ((err = StateSensor::Validate(UTILITY_LINE_CONDITION, lbtmp)) == ErrNO_ERROR) { Event evt(UTILITY_LINE_CONDITION, LINE_BAD); storeValue(lbtmp); UpdateObj::Update(&evt); } } else { theLineFailCount++; } } break; case NO_ABNORMAL_CONDITION: { theLineFailCount = 0; CHAR lbtmp[31]; sprintf(lbtmp, "%d", LINE_GOOD); if ((err = StateSensor::Validate(UTILITY_LINE_CONDITION, lbtmp)) == ErrNO_ERROR) { Event evt(UTILITY_LINE_CONDITION, LINE_GOOD); storeValue(lbtmp); UpdateObj::Update(&evt); } } break; } // switch for case LINE_CONDITION_TEST break; case UTILITY_LINE_CONDITION: if ((err = Validate(aCode, aValue)) == ErrNO_ERROR) { storeValue(aValue); UpdateObj::Update(anEvent); } break; case SIMULATE_POWER_FAIL: switch(atoi(aValue)) { case SIMULATE_POWER_FAIL: SET_BIT(theUpsState, SIMULATE_POWER_FAIL_BIT); break; case SIMULATE_POWER_FAIL_OVER: CLEAR_BIT(theUpsState, SIMULATE_POWER_FAIL_BIT); break; } break; case SELF_TEST_STATE: switch(atoi(aValue)) { case SELF_TEST_IN_PROGRESS: SET_BIT(theUpsState, SELF_TEST_BIT); break; case NO_SELF_TEST_IN_PROGRESS: CLEAR_BIT(theUpsState, SELF_TEST_BIT); break; } break; } return err; } INT UtilityLineConditionSensor::Validate(INT aCode, const PCHAR aValue) { INT err = ErrNO_ERROR; if (aCode != theSensorCode) { err = ErrINVALID_CODE; } else if(IS_STATE(UPS_STATE_IN_SELF_TEST)) { err = ErrTEST_IN_PROGRESS; } else { switch(atoi(aValue)) { case LINE_GOOD: { theLineFailCount = 0; // // Make sure line is good to handle UPSLinkism // that doesnt change tranfer cause when line // fails during self test or sim pwrfail // CHAR line_state[32]; theCommController->Get(LINE_CONDITION_TEST, line_state); if(atoi(line_state) == ABNORMAL_CONDITION) { err = ErrINVALID_VALUE; } break; } case LINE_BAD: // // Dont do this if we're a BackUPS // if (theDevice->IsA() != BACKUPS) { // // If we're in DeepDischarge ignore LINE_BAD events // if(theInformationSource != NINECOMMAND) { // // If we're simulating a power fail // don't try to stop the event // if(!(IS_STATE(UPS_STATE_SIMULATED_POWER_FAIL))) { CHAR transfer_cause[32]; CHAR self_test[32]; CHAR line_state[32]; // // If transfer is due to a self test double check // to see if line is bad // theCommController->Get(TRANSFER_CAUSE, transfer_cause); _itoa(SELF_TEST_TRANSFER, self_test, 10); if (strcmp(transfer_cause, self_test) == 0) { // // Make sure line is bad to handle UPSLinkism // that doesnt change tranfer cause when line // fails during self test or sim pwrfail // theCommController->Get(LINE_CONDITION_TEST, line_state); if(atoi(line_state) == NO_ABNORMAL_CONDITION) { err = ErrINVALID_VALUE; } else { // // Wait a while to handle UPS-Linkism for // the 9 command that returns 00 at the start // of a self test // _theTimerManager->Wait(3000L); theCommController->Get(LINE_CONDITION_TEST, line_state); if(atoi(line_state) == NO_ABNORMAL_CONDITION) { err = ErrINVALID_VALUE; } } } // // Same for Lights Test // CHAR ups_status[32]; theDevice->Get(UPS_STATE, ups_status); if (atoi(ups_status) & UPS_STATE_IN_LIGHTS_TEST) { err = ErrINVALID_VALUE; } } } } // if (!= BACKUPS) break; default: err = ErrINVALID_VALUE; break; } if (err == ErrNO_ERROR) { err = StateSensor::Validate(aCode, aValue); } } return err; } UtilityLineConditionSensor :: ~UtilityLineConditionSensor() { if (theCommController) theCommController->UnregisterEvent(UTILITY_LINE_CONDITION, this); if (theDevice) { theDevice->UnregisterEvent(BATTERY_CALIBRATION_CONDITION, this); theDevice->UnregisterEvent(SIMULATE_POWER_FAIL, this); theDevice->UnregisterEvent(SELF_TEST_STATE, this); } }