void ControlLogic::getSensorUpdate()

in fboss/platform/fan_service/ControlLogic.cpp [245:387]


void ControlLogic::getSensorUpdate() {
  std::string sensorItemName;
  float rawValue = 0.0, adjustedValue, targetPwm;
  uint64_t calculatedTime = 0;
  for (auto configSensorItem = pConfig_->sensors.begin();
       configSensorItem != pConfig_->sensors.end();
       ++configSensorItem) {
    XLOG(INFO) << "Control :: Sensor Name : " << configSensorItem->sensorName;
    bool sensorAccessFail = false;
    sensorItemName = configSensorItem->sensorName;
    if (pSensor_->checkIfEntryExists(sensorItemName)) {
      XLOG(INFO) << "Control :: Sensor Exists. Getting the entry type";
      // 1.a Get the reading
      SensorEntryType entryType = pSensor_->getSensorEntryType(sensorItemName);
      switch (entryType) {
        case SensorEntryType::kSensorEntryInt:
          rawValue = pSensor_->getSensorDataInt(sensorItemName);
          rawValue = rawValue / configSensorItem->scale;
          break;
        case SensorEntryType::kSensorEntryFloat:
          rawValue = pSensor_->getSensorDataFloat(sensorItemName);
          rawValue = rawValue / configSensorItem->scale;
          break;
        default:
          facebook::fboss::FbossError(
              "Invalid Sensor Entry Type in entry name : ", sensorItemName);
          break;
      }
    } else {
      XLOG(ERR) << "Control :: Sensor Read Fail : " << sensorItemName;
      sensorAccessFail = true;
    }
    XLOG(INFO) << "Control :: Done raw sensor reading";

    if (sensorAccessFail) {
      // If the sensor data cache is stale for a while, we consider it as the
      // failure of such sensor
      uint64_t timeDiffInSec = pBsp_->getCurrentTime() -
          configSensorItem->processedData.lastUpdatedTime;
      if (timeDiffInSec >= configSensorItem->sensorFailThresholdInSec) {
        configSensorItem->processedData.sensorFailed == true;
        numSensorFailed_++;
      }
    } else {
      calculatedTime = pSensor_->getLastUpdated(sensorItemName);
      configSensorItem->processedData.lastUpdatedTime = calculatedTime;
      configSensorItem->processedData.sensorFailed = false;
    }

    // 1.b If adjustment table exists, adjust the raw value
    if (configSensorItem->offsetTable.size() == 0) {
      adjustedValue = rawValue;
    } else {
      float offset = 0;
      for (auto tableEntry = configSensorItem->offsetTable.begin();
           tableEntry != configSensorItem->offsetTable.end();
           ++tableEntry) {
        if (rawValue >= tableEntry->first) {
          offset = tableEntry->second;
        }
        adjustedValue = rawValue + offset;
      }
    }
    configSensorItem->processedData.adjustedReadCache = adjustedValue;
    XLOG(INFO) << "Control :: Adjusted Value : " << adjustedValue;
    // 1.c Check and trigger alarm
    bool prevMajorAlarm = configSensorItem->processedData.majorAlarmTriggered;
    configSensorItem->processedData.majorAlarmTriggered =
        (adjustedValue >= configSensorItem->alarm.high_major);
    // If major alarm was triggered, write it as a ERR log
    if (!prevMajorAlarm &&
        configSensorItem->processedData.majorAlarmTriggered) {
      XLOG(ERR) << "Major Alarm Triggered on " << configSensorItem->sensorName
                << " at value " << adjustedValue;
    } else if (
        prevMajorAlarm &&
        !configSensorItem->processedData.majorAlarmTriggered) {
      XLOG(WARN) << "Major Alarm Cleared on " << configSensorItem->sensorName
                 << " at value " << adjustedValue;
    }
    bool prevMinorAlarm = configSensorItem->processedData.minorAlarmTriggered;
    if (adjustedValue >= configSensorItem->alarm.high_minor) {
      if (configSensorItem->processedData.soakStarted) {
        uint64_t timeDiffInSec = pBsp_->getCurrentTime() -
            configSensorItem->processedData.soakStartedAt;
        if (timeDiffInSec >= configSensorItem->alarm.high_minor_soak) {
          configSensorItem->processedData.minorAlarmTriggered = true;
          configSensorItem->processedData.soakStarted = false;
        }
      } else {
        configSensorItem->processedData.soakStarted = true;
        configSensorItem->processedData.soakStartedAt = calculatedTime;
      }
    } else {
      configSensorItem->processedData.minorAlarmTriggered = false;
      configSensorItem->processedData.soakStarted = false;
    }
    // If minor alarm was triggered, write it as a WARN log
    if (!prevMinorAlarm &&
        configSensorItem->processedData.minorAlarmTriggered) {
      XLOG(WARN) << "Minor Alarm Triggered on " << configSensorItem->sensorName
                 << " at value " << adjustedValue;
    }
    if (prevMinorAlarm &&
        !configSensorItem->processedData.minorAlarmTriggered) {
      XLOG(WARN) << "Minor Alarm Cleared on " << configSensorItem->sensorName
                 << " at value " << adjustedValue;
    }
    // 1.d Check the range (if required), and do emergency
    // shutdown, if the value is out of range for more than
    // the "tolerance" times
    if (configSensorItem->rangeCheck.enabled) {
      if ((adjustedValue > configSensorItem->rangeCheck.rangeHigh) ||
          (adjustedValue < configSensorItem->rangeCheck.rangeLow)) {
        configSensorItem->rangeCheck.invalidCount += 1;
        if (configSensorItem->rangeCheck.invalidCount >=
            configSensorItem->rangeCheck.tolerance) {
          // ERR log only once.
          if (configSensorItem->rangeCheck.invalidCount ==
              configSensorItem->rangeCheck.tolerance) {
            XLOG(ERR) << "Sensor " << configSensorItem->sensorName
                      << " out of range for too long!";
          }
          // If we are not yet in emergency state, do the emergency shutdown.
          if ((configSensorItem->rangeCheck.action ==
               kRangeCheckActionShutdown) &&
              (pBsp_->getEmergencyState() == false)) {
            pBsp_->emergencyShutdown(pConfig_, true);
          }
        }
      } else {
        configSensorItem->rangeCheck.invalidCount = 0;
      }
    }
    // 1.e Calculate the target pwm in percent
    //     (the table or incremental pid should produce
    //      percent as its output)
    updateTargetPwm(&(*configSensorItem));
    XLOG(INFO) << configSensorItem->sensorName << " has the target PWM of "
               << configSensorItem->processedData.targetPwmCache;
  }
  return;
}