CycloneTechnology/ChaMP

View on GitHub
champ-ipmi/src/main/scala/com/cyclone/ipmi/command/chassis/GetChassisStatus.scala

Summary

Maintainability
A
0 mins
Test Coverage
package com.cyclone.ipmi.command.chassis

import akka.util.ByteString
import com.cyclone.ipmi.codec._
import com.cyclone.ipmi.command.{CommandCode, NetworkFunction, StatusCodeTranslator}
import com.cyclone.ipmi.protocol.packet.{CommandResultCodec, IpmiCommandResult, IpmiStandardCommand}

/**
  * Get Chassis Status command and response
  */
object GetChassisStatus {

  sealed trait PowerRestorePolicy

  object PowerRestorePolicy {
    implicit val decoder: Decoder[PowerRestorePolicy] = new Decoder[PowerRestorePolicy] {

      def decode(data: ByteString): PowerRestorePolicy = data(0).bits5To6.toUnsignedInt match {
        case 0 => StaysPoweredOff
        case 1 => RestoreState
        case 2 => PowerUp
        case 3 => Unknown
      }
    }

    case object StaysPoweredOff extends PowerRestorePolicy

    case object RestoreState extends PowerRestorePolicy

    case object PowerUp extends PowerRestorePolicy

    case object Unknown extends PowerRestorePolicy

  }

  object CurrentPowerState {
    implicit val decoder: Decoder[CurrentPowerState] = new Decoder[CurrentPowerState] {

      def decode(data: ByteString): CurrentPowerState = {
        val byte = data(0)

        CurrentPowerState(
          restorePolicy = byte.as[PowerRestorePolicy],
          controlFault = byte.bit4,
          fault = byte.bit3,
          interlock = byte.bit4,
          overload = byte.bit1,
          on = byte.bit0
        )
      }
    }
  }

  case class CurrentPowerState(
    restorePolicy: PowerRestorePolicy,
    controlFault: Boolean,
    fault: Boolean,
    interlock: Boolean,
    overload: Boolean,
    on: Boolean
  )

  object LastPowerEvent {
    implicit val decoder: Decoder[LastPowerEvent] = new Decoder[LastPowerEvent] {

      def decode(data: ByteString): LastPowerEvent = {
        val byte = data(0)

        LastPowerEvent(
          onByIpmi = byte.bit4,
          causedByFault = byte.bit3,
          causedByInterlock = byte.bit2,
          causedByOverload = byte.bit1,
          causedByAcFailed = byte.bit0
        )
      }
    }
  }

  case class LastPowerEvent(
    onByIpmi: Boolean,
    causedByFault: Boolean,
    causedByInterlock: Boolean,
    causedByOverload: Boolean,
    causedByAcFailed: Boolean
  )

  sealed trait ChassisIdentifyState

  object ChassisIdentifyState {
    implicit val decoder: Decoder[ChassisIdentifyState] = new Decoder[ChassisIdentifyState] {

      def decode(data: ByteString): ChassisIdentifyState =
        data(0).toUnsignedInt match {
          case 0 => Off
          case 1 => Temporary
          case 2 => Indefinite
          case 3 => Reserved
        }
    }

    case object Off extends ChassisIdentifyState

    case object Temporary extends ChassisIdentifyState

    case object Indefinite extends ChassisIdentifyState

    // For reserved value
    case object Reserved extends ChassisIdentifyState

  }

  object MiscChassisState {
    implicit val decoder: Decoder[MiscChassisState] = new Decoder[MiscChassisState] {

      def decode(data: ByteString): MiscChassisState = {
        val byte = data(0)

        MiscChassisState(
          identifyState = if (byte.bit6) None else Some(byte.bits4To5.as[ChassisIdentifyState]),
          coolingFault = byte.bit3,
          driveFault = byte.bit2,
          frontPanelLockout = byte.bit1,
          chassisIntrusion = byte.bit0
        )
      }
    }
  }

  case class MiscChassisState(
    identifyState: Option[ChassisIdentifyState],
    coolingFault: Boolean,
    driveFault: Boolean,
    frontPanelLockout: Boolean,
    chassisIntrusion: Boolean
  )

  object FrontPanelButtonCapabilities {
    implicit val decoder: Decoder[FrontPanelButtonCapabilities] =
      new Decoder[FrontPanelButtonCapabilities] {

        def decode(data: ByteString): FrontPanelButtonCapabilities = {
          val byte = data(0)

          FrontPanelButtonCapabilities(
            standbyAllowed = byte.bit7,
            diagnosticInterruptDisableAllowed = byte.bit6,
            resetDisableAllowed = byte.bit5,
            powerOffDisableAllowed = byte.bit4,
            standbyDisabled = byte.bit3,
            diagnosticInterruptDisabled = byte.bit2,
            resetDisabled = byte.bit1,
            powerOffDisabled = byte.bit0
          )
        }
      }
  }

  case class FrontPanelButtonCapabilities(
    standbyAllowed: Boolean,
    diagnosticInterruptDisableAllowed: Boolean,
    resetDisableAllowed: Boolean,
    powerOffDisableAllowed: Boolean,
    standbyDisabled: Boolean,
    diagnosticInterruptDisabled: Boolean,
    resetDisabled: Boolean,
    powerOffDisabled: Boolean
  )

  object CommandResult {
    implicit val decoder: Decoder[CommandResult] = new Decoder[CommandResult] {

      def decode(data: ByteString): CommandResult = {
        val iterator = data.iterator
        val is = iterator.asInputStream

        val currentPowerState = is.readByte.as[CurrentPowerState]
        val lastPowerEvent = is.readByte.as[LastPowerEvent]
        val miscChassisState = is.readByte.as[MiscChassisState]
        val frontPanelButtonCapabilities =
          is.readByteOptional.map(_.as[FrontPanelButtonCapabilities])

        CommandResult(
          currentPowerState,
          lastPowerEvent,
          miscChassisState,
          frontPanelButtonCapabilities
        )
      }
    }

    implicit val statusCodeTranslator: StatusCodeTranslator[CommandResult] =
      StatusCodeTranslator[CommandResult]()
  }

  case class CommandResult(
    currentPowerState: CurrentPowerState,
    lastPowerEvent: LastPowerEvent,
    miscChassisState: MiscChassisState,
    frontPanelButtonCapabilities: Option[FrontPanelButtonCapabilities]
  ) extends IpmiCommandResult

  object Command extends IpmiStandardCommand {
    implicit val coder: Coder[Command.type] = new Coder[Command.type] {

      def encode(request: Command.type): ByteString =
        ByteString.empty
    }

    implicit val codec: CommandResultCodec[Command.type, CommandResult] =
      CommandResultCodec.commandResultCodecFor[Command.type, CommandResult]

    val networkFunction: NetworkFunction = NetworkFunction.ChassisRequest
    val commandCode = CommandCode(0x01)
  }

}