436 lines
14 KiB
C++
436 lines
14 KiB
C++
/*
|
|
*
|
|
* REVISIONS:
|
|
*/
|
|
|
|
|
|
#include "cdefine.h"
|
|
|
|
extern "C" {
|
|
#include <stdlib.h>
|
|
}
|
|
|
|
#include "_defs.h"
|
|
#include "servapp.h"
|
|
#include "codes.h"
|
|
#include "cfgmgr.h"
|
|
#include "trans.h"
|
|
#include "timerman.h"
|
|
#include "sysstate.h"
|
|
#include "event.h"
|
|
|
|
#include "utils.h"
|
|
// Retry a failed construction every 3 seconds
|
|
//const INT RETRY_CONSTRUCT_DELAY = 3000;
|
|
const INT RETRY_CONSTRUCT_DELAY = 3;
|
|
|
|
|
|
// When setting the port name, it might fix comm on its own
|
|
// making this == 0 will force a rebuild immediately, on
|
|
// the same thread
|
|
//
|
|
// #define WAIT_FOR_SET_TO_WORK 250 // 1/4 seconds
|
|
#define WAIT_FOR_SET_TO_WORK 1 /* 1 second */
|
|
|
|
// theDeviceControllerInitialized values
|
|
#define NEVER_DONE 0
|
|
#define IN_PROGRESS 1
|
|
#define COMPLETED 2
|
|
|
|
|
|
// This should be initialized in the main module
|
|
|
|
PServerApplication _theApp = NULL;
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
ServerApplication::ServerApplication() :
|
|
theTimerID(0),
|
|
theDeviceControllerInitialized(NEVER_DONE),
|
|
theForceDeviceRebuildFlag(FALSE),
|
|
theDeviceController((PDeviceController)NULL)
|
|
{
|
|
_theApp = this;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
ServerApplication::~ServerApplication()
|
|
{
|
|
if (theTimerID) {
|
|
|
|
if (_theTimerManager) {
|
|
_theTimerManager->CancelTimer(theTimerID);
|
|
}
|
|
theTimerID = 0;
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Start()
|
|
{
|
|
|
|
// set the timezone variables
|
|
SetTimeZone();
|
|
|
|
Event start_event(MONITORING_STATUS, MONITORING_STARTED);
|
|
Update(&start_event);
|
|
|
|
CreateDeviceController((PEvent)NULL);
|
|
|
|
InitializeDeviceController();
|
|
|
|
return ErrNO_ERROR;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
VOID ServerApplication::Quit()
|
|
{
|
|
DisableEvents(); //srt28Mar97
|
|
|
|
// Tell everyone that the service is stopping
|
|
Event start_event(MONITORING_STATUS, MONITORING_STOPPED);
|
|
Update(&start_event);
|
|
|
|
// Stop all active threads ... NOTE that they are stopped
|
|
// in a specific order. theDataLog is independent and is stopped first,
|
|
// theDeviceController will stop the UPS polling. theServerController
|
|
// will stop all incoming client requests and current connections. Finally,
|
|
// theTimerManager will stop executing timed events.
|
|
if (theDeviceController) {
|
|
theDeviceController->Stop();
|
|
}
|
|
|
|
if (_theTimerManager) {
|
|
_theTimerManager->Stop();
|
|
}
|
|
|
|
// Return to simple signalling
|
|
theDeviceController->Set(TURN_OFF_SMART_MODE, NULL);
|
|
|
|
delete theDeviceController;
|
|
theDeviceController = NULL;
|
|
|
|
delete _theTimerManager;
|
|
_theTimerManager = theTimerManager = NULL;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Set(INT code,const PCHAR value)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
|
|
switch(code/1000) {
|
|
case 0: // Ups
|
|
case 1: // Measure ups
|
|
|
|
if (theDeviceController) {
|
|
err = theDeviceController->Set(code,value);
|
|
}
|
|
else {
|
|
err = ErrCOMMUNICATION_LOST;
|
|
}
|
|
break;
|
|
|
|
case 2: // Host
|
|
|
|
if (code == RESET_UPS_COMM_PORT) {
|
|
// Set this TRUE. If just setting the .ini file value
|
|
// causes the retry to succeed, then the flag will be
|
|
// reset and we won't bother forcing a rebuild
|
|
// Note that by sending the event on the timer thread,
|
|
// we serialize with the retries.
|
|
//
|
|
theForceDeviceRebuildFlag = TRUE;
|
|
|
|
Event ev(COMMUNICATION_STATE, UPS_COMM_PORT_CHANGED);
|
|
|
|
#if (WAIT_FOR_SET_TO_WORK > 0)
|
|
_theTimerManager->SetTheTimer(WAIT_FOR_SET_TO_WORK, &ev, this);
|
|
#else
|
|
Update(&ev);
|
|
#endif
|
|
}
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Set(PTransactionItem trans)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Get(INT code, PCHAR value)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
|
|
switch(code/1000) {
|
|
case 0: // Ups
|
|
if (code == SYSTEM_STATE || code == UPS_STATE) {
|
|
//
|
|
// Really all we want is sytem state. Ups state hangs around
|
|
// to be compatible with old software (PowerNet)
|
|
//
|
|
ULONG system_state = 0;
|
|
if (theDeviceController) {
|
|
value[0] = 0;
|
|
err = theDeviceController->Get(COMMUNICATION_STATE, value);
|
|
ULONG comm_state = atol(value);
|
|
if (comm_state == COMMUNICATION_ESTABLISHED) {
|
|
|
|
//
|
|
// Only get UPS State if we have Comm
|
|
//
|
|
value[0] = 0;
|
|
err = theDeviceController->Get(UPS_STATE, value);
|
|
system_state = atol(value);
|
|
|
|
//
|
|
// Just to make sure
|
|
//
|
|
CLEAR_BIT(system_state, COMMUNICATIONS_BIT);
|
|
CLEAR_BIT(system_state, SHUTDOWN_IN_PROGRESS_BIT);
|
|
}
|
|
else {
|
|
//
|
|
// pcy - I don't know why we don't return communication
|
|
// lost as an error here, but we do below.
|
|
//
|
|
SET_BIT(system_state, COMMUNICATIONS_BIT);
|
|
}
|
|
_ltoa(system_state, value, 10);
|
|
}
|
|
else {
|
|
SET_BIT(system_state, COMMUNICATIONS_BIT);
|
|
_ltoa(system_state, value, 10);
|
|
err = ErrCOMMUNICATION_LOST;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case 1: // Measure ups
|
|
value[0] = 0;
|
|
if (theDeviceController) {
|
|
err = theDeviceController->Get(code,value);
|
|
}
|
|
else {
|
|
err = ErrCOMMUNICATION_LOST;
|
|
}
|
|
break;
|
|
|
|
case 2: // Host
|
|
// printf("Getting from host\n");
|
|
value[0] = 0;
|
|
break;
|
|
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Get(PTransactionItem trans)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
return err;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::Update(PEvent anEvent)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
int sentEventOn = FALSE;
|
|
|
|
// If the communication is lost or we change ports, then
|
|
// schedule a rebuild of the device controller
|
|
if (anEvent->GetCode() == COMMUNICATION_STATE) {
|
|
switch(atoi(anEvent->GetValue())) {
|
|
|
|
case UPS_COMM_PORT_CHANGED:
|
|
|
|
if (theForceDeviceRebuildFlag) {
|
|
err = MainApplication::Update(anEvent);
|
|
sentEventOn = TRUE;
|
|
theDeviceController->Set(RETRY_CONSTRUCT, "Yes");
|
|
}
|
|
break;
|
|
|
|
case COMMUNICATION_ESTABLISHED:
|
|
|
|
if (theDeviceControllerInitialized == NEVER_DONE) {
|
|
err = InitializeDeviceController();
|
|
}
|
|
theForceDeviceRebuildFlag = FALSE;
|
|
// Fall through
|
|
}
|
|
}
|
|
|
|
if (!sentEventOn) {
|
|
err = MainApplication::Update(anEvent);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
VOID ServerApplication::DisableEvents()
|
|
{
|
|
if (theDeviceController) {
|
|
theDeviceController->UnregisterEvent(UTILITY_LINE_CONDITION,this);
|
|
theDeviceController->UnregisterEvent(BATTERY_CONDITION,this);
|
|
theDeviceController->UnregisterEvent(RUN_TIME_EXPIRED,this);
|
|
theDeviceController->UnregisterEvent(RUN_TIME_REMAINING,this);
|
|
theDeviceController->UnregisterEvent(UPS_OFF_PENDING,this);
|
|
// Register with the device for Shutdown - this will happen when the
|
|
// server is a slave
|
|
theDeviceController->UnregisterEvent(SHUTDOWN,this);
|
|
theDeviceController->UnregisterEvent(SMART_BOOST_STATE,this);
|
|
theDeviceController->UnregisterEvent(SMART_TRIM_STATE,this);
|
|
theDeviceController->UnregisterEvent(UPS_LOAD,this);
|
|
theDeviceController->UnregisterEvent(COMMUNICATION_STATE,this);
|
|
theDeviceController->UnregisterEvent(SELF_TEST_RESULT,this);
|
|
theDeviceController->UnregisterEvent(BATTERY_CALIBRATION_CONDITION,this);
|
|
theDeviceController->UnregisterEvent(MIN_LINE_VOLTAGE,this);
|
|
theDeviceController->UnregisterEvent(MAX_LINE_VOLTAGE,this);
|
|
theDeviceController->UnregisterEvent(BYPASS_MODE, this);
|
|
theDeviceController->UnregisterEvent(MATRIX_FAN_STATE, this);
|
|
theDeviceController->UnregisterEvent(BYPASS_POWER_SUPPLY_CONDITION, this);
|
|
theDeviceController->UnregisterEvent(SMART_CELL_SIGNAL_CABLE_STATE, this);
|
|
theDeviceController->UnregisterEvent(REDUNDANCY_STATE, this);
|
|
theDeviceController->UnregisterEvent(UPS_MODULE_ADDED, this);
|
|
theDeviceController->UnregisterEvent(UPS_MODULE_REMOVED, this);
|
|
theDeviceController->UnregisterEvent(UPS_MODULE_FAILED, this);
|
|
theDeviceController->UnregisterEvent(BATTERY_ADDED, this);
|
|
theDeviceController->UnregisterEvent(BATTERY_REMOVED, this);
|
|
theDeviceController->UnregisterEvent(IM_OK, this);
|
|
theDeviceController->UnregisterEvent(IM_FAILED, this);
|
|
theDeviceController->UnregisterEvent(IM_INSTALLATION_STATE, this);
|
|
theDeviceController->UnregisterEvent(RIM_INSTALLATION_STATE, this);
|
|
theDeviceController->UnregisterEvent(RIM_OK, this);
|
|
theDeviceController->UnregisterEvent(RIM_FAILED, this);
|
|
theDeviceController->UnregisterEvent(SYSTEM_FAN_STATE, this);
|
|
theDeviceController->UnregisterEvent(BYPASS_CONTACTOR_STATE, this);
|
|
theDeviceController->UnregisterEvent(INPUT_BREAKER_STATE, this);
|
|
theDeviceController->UnregisterEvent(UPS_TEMPERATURE, this);
|
|
|
|
// MeasureUPS Events
|
|
theDeviceController->UnregisterEvent(AMBIENT_TEMPERATURE,this);
|
|
theDeviceController->UnregisterEvent(HUMIDITY,this);
|
|
theDeviceController->UnregisterEvent(CONTACT_STATE,this);
|
|
|
|
theDeviceController->UnregisterEvent(IM_STATUS,this);
|
|
theDeviceController->UnregisterEvent(RIM_STATUS,this);
|
|
theDeviceController->UnregisterEvent(BATTERY_REPLACEMENT_CONDITION,this);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
INT ServerApplication::CreateDeviceController (PEvent anEvent)
|
|
{
|
|
INT err = ErrNO_ERROR;
|
|
|
|
// printf("Entering CreateDeviceController\n");
|
|
|
|
// Delete any existing device controller
|
|
if (theDeviceController) {
|
|
delete theDeviceController;
|
|
theDeviceController = (PDeviceController)NULL;
|
|
}
|
|
|
|
// Now create a new device controller
|
|
theDeviceController = new DeviceController(this);
|
|
|
|
theDeviceController->RegisterEvent(UTILITY_LINE_CONDITION,this);
|
|
theDeviceController->RegisterEvent(BATTERY_CONDITION,this);
|
|
theDeviceController->RegisterEvent(RUN_TIME_EXPIRED,this);
|
|
theDeviceController->RegisterEvent(RUN_TIME_REMAINING,this);
|
|
theDeviceController->RegisterEvent(UPS_OFF_PENDING,this);
|
|
// Register with the device for Shutdown - this will happen when the
|
|
// server is a slave
|
|
theDeviceController->RegisterEvent(SHUTDOWN,this);
|
|
theDeviceController->RegisterEvent(SMART_BOOST_STATE,this);
|
|
theDeviceController->RegisterEvent(SMART_TRIM_STATE,this);
|
|
theDeviceController->RegisterEvent(UPS_LOAD,this);
|
|
theDeviceController->RegisterEvent(COMMUNICATION_STATE,this);
|
|
theDeviceController->RegisterEvent(SELF_TEST_RESULT,this);
|
|
theDeviceController->RegisterEvent(BATTERY_CALIBRATION_CONDITION,this);
|
|
theDeviceController->RegisterEvent(MIN_LINE_VOLTAGE,this);
|
|
theDeviceController->RegisterEvent(MAX_LINE_VOLTAGE,this);
|
|
theDeviceController->RegisterEvent(BYPASS_MODE, this);
|
|
theDeviceController->RegisterEvent(MATRIX_FAN_STATE, this);
|
|
theDeviceController->RegisterEvent(BYPASS_POWER_SUPPLY_CONDITION, this);
|
|
theDeviceController->RegisterEvent(SMART_CELL_SIGNAL_CABLE_STATE, this);
|
|
theDeviceController->RegisterEvent(REDUNDANCY_STATE, this);
|
|
theDeviceController->RegisterEvent(UPS_MODULE_ADDED, this);
|
|
theDeviceController->RegisterEvent(UPS_MODULE_REMOVED, this);
|
|
theDeviceController->RegisterEvent(UPS_MODULE_FAILED, this);
|
|
theDeviceController->RegisterEvent(BATTERY_ADDED, this);
|
|
theDeviceController->RegisterEvent(BATTERY_REMOVED, this);
|
|
theDeviceController->RegisterEvent(IM_STATUS, this);
|
|
theDeviceController->RegisterEvent(IM_OK, this);
|
|
theDeviceController->RegisterEvent(IM_FAILED, this);
|
|
theDeviceController->RegisterEvent(IM_INSTALLATION_STATE, this);
|
|
theDeviceController->RegisterEvent(RIM_INSTALLATION_STATE, this);
|
|
theDeviceController->RegisterEvent(RIM_STATUS, this);
|
|
theDeviceController->RegisterEvent(RIM_OK, this);
|
|
theDeviceController->RegisterEvent(RIM_FAILED, this);
|
|
theDeviceController->RegisterEvent(SYSTEM_FAN_STATE, this);
|
|
theDeviceController->RegisterEvent(BYPASS_CONTACTOR_STATE, this);
|
|
theDeviceController->RegisterEvent(INPUT_BREAKER_STATE, this);
|
|
theDeviceController->RegisterEvent(UPS_TEMPERATURE, this);
|
|
theDeviceController->RegisterEvent(TOTAL_INVERTERS, this);
|
|
theDeviceController->RegisterEvent(NUMBER_BAD_INVERTERS, this);
|
|
theDeviceController->RegisterEvent(BAD_BATTERY_PACKS, this);
|
|
theDeviceController->RegisterEvent(EXTERNAL_BATTERY_PACKS, this);
|
|
theDeviceController->RegisterEvent(BATTERY_REPLACEMENT_CONDITION, this);
|
|
|
|
// MeasureUPS Events
|
|
theDeviceController->RegisterEvent(AMBIENT_TEMPERATURE,this);
|
|
theDeviceController->RegisterEvent(HUMIDITY,this);
|
|
theDeviceController->RegisterEvent(CONTACT_STATE,this);
|
|
|
|
return err;
|
|
}
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|
|
INT ServerApplication::InitializeDeviceController()
|
|
{
|
|
INT err = theDeviceController->GetObjectStatus();
|
|
|
|
// Make sure that the object constructed ok
|
|
|
|
if (err == ErrNO_ERROR) {
|
|
theDeviceControllerInitialized = IN_PROGRESS;
|
|
err = theDeviceController->Initialize();
|
|
|
|
if (err == ErrNO_ERROR) {
|
|
theDeviceControllerInitialized = COMPLETED;
|
|
}
|
|
}
|
|
return err;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
|