      util::sleep_for(500);
    }
  }
  
  void hardware_control_thread(Panda *panda) {
    LOGD("start hardware control thread");
    SubMaster sm({"deviceState", "driverCameraState"});
  
    uint64_t last_front_frame_t = 0;
    uint16_t prev_fan_speed = 999;
    uint16_t ir_pwr = 0;
 
</s> remove void panda_state_thread(PubMaster *pm, Panda *panda, bool spoofing_started) {
  LOGD("start panda state thread");
  uint32_t no_ignition_cnt = 0;
  bool ignition_last = false;
  Params params = Params();
 </s> add bool send_panda_state(PubMaster *pm, Panda *panda, bool spoofing_started) {
  health_t pandaState = panda->get_state(); </s> remove #endif
 </s> add   } else {
    ps.setVoltage(pandaState.voltage);
    ps.setCurrent(pandaState.current);
  }

  uint16_t fan_speed_rpm = panda->get_fan_speed();
  ps.setUsbPowerMode(cereal::PeripheralState::UsbPowerMode(pandaState.usb_power_mode));
  ps.setFanSpeedRpm(fan_speed_rpm);

  pm->send("peripheralState", msg);
}

void panda_state_thread(PubMaster *pm, Panda * peripheral_panda, Panda *panda, bool spoofing_started) {
  Params params;
  bool ignition_last = false;

  LOGD("start panda state thread");

  // run at 2hz
  while (!do_exit && panda->connected) {
    send_peripheral_state(pm, peripheral_panda);
    ignition = send_panda_state(pm, panda, spoofing_started); </s> remove     uint16_t fan_speed_rpm = panda->get_fan_speed();

    // build msg
    MessageBuilder msg;
    auto evt = msg.initEvent();
    evt.setValid(panda->comms_healthy);

    auto ps = evt.initPandaState();
    ps.setUptime(pandaState.uptime);

    if (Hardware::TICI()) {
      double read_time = millis_since_boot();
      ps.setVoltage(std::atoi(util::read_file("/sys/class/hwmon/hwmon1/in1_input").c_str()));
      ps.setCurrent(std::atoi(util::read_file("/sys/class/hwmon/hwmon1/curr1_input").c_str()));
      read_time = millis_since_boot() - read_time;
      if (read_time > 50) {
        LOGW("reading hwmon took %lfms", read_time);
      }
    } else {
      ps.setVoltage(pandaState.voltage);
      ps.setCurrent(pandaState.current);
    }
 </s> add  </s> remove     ps.setIgnitionLine(pandaState.ignition_line);
    ps.setIgnitionCan(pandaState.ignition_can);
    ps.setControlsAllowed(pandaState.controls_allowed);
    ps.setGasInterceptorDetected(pandaState.gas_interceptor_detected);
    ps.setHasGps(true);
    ps.setCanRxErrs(pandaState.can_rx_errs);
    ps.setCanSendErrs(pandaState.can_send_errs);
    ps.setCanFwdErrs(pandaState.can_fwd_errs);
    ps.setGmlanSendErrs(pandaState.gmlan_send_errs);
    ps.setPandaType(panda->hw_type);
    ps.setUsbPowerMode(cereal::PandaState::UsbPowerMode(pandaState.usb_power_mode));
    ps.setSafetyModel(cereal::CarParams::SafetyModel(pandaState.safety_model));
    ps.setSafetyParam(pandaState.safety_param);
    ps.setFanSpeedRpm(fan_speed_rpm);
    ps.setFaultStatus(cereal::PandaState::FaultStatus(pandaState.fault_status));
    ps.setPowerSaveEnabled((bool)(pandaState.power_save_enabled));
    ps.setHeartbeatLost((bool)(pandaState.heartbeat_lost));
    ps.setHarnessStatus(cereal::PandaState::HarnessStatus(pandaState.car_harness_status));

    // Convert faults bitset to capnp list
    std::bitset<sizeof(pandaState.faults) * 8> fault_bits(pandaState.faults);
    auto faults = ps.initFaults(fault_bits.count());

    size_t i = 0;
    for (size_t f = size_t(cereal::PandaState::FaultType::RELAY_MALFUNCTION);
        f <= size_t(cereal::PandaState::FaultType::INTERRUPT_RATE_TICK); f++) {
      if (fault_bits.test(f)) {
        faults.set(i, cereal::PandaState::FaultType(f));
        i++;
      }
    }
    pm->send("pandaState", msg);
 </s> add 
void peripheral_control_thread(Panda *panda) {
  LOGD("start peripheral control thread");
      util::sleep_for(500);
    }
  }
  
void peripheral_control_thread(Panda *panda) {
  LOGD("start peripheral control thread");
void peripheral_control_thread(Panda *panda) {
  LOGD("start peripheral control thread");
    SubMaster sm({"deviceState", "driverCameraState"});
  
    uint64_t last_front_frame_t = 0;
    uint16_t prev_fan_speed = 999;
    uint16_t ir_pwr = 0;
keep keep keep keep replace replace keep keep keep keep keep
 Split pandaState into peripheralState and pandaState (#22385)

* publish peripheralState from boardd

* refactor consumers

* rename thread

* peripheralState has panda type too

* add to process replay

* fix device build

* properly remove hardware unsupported alert

* latest peripheralState

* remove pandaState from thermal_monitor

* put that back

* add back harness check

* fix cloudlog

* needs pandaState

* Update selfdrive/thermald/tests/test_power_monitoring.py

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* dont conflate

* Update selfdrive/thermald/tests/test_power_monitoring.py

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* pigeon is peripheral

* cleanup

* less global

* comment

* move rtc to peripheral_control_thread

* better diff?

* whitespace

* get msg

* bump cereal

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> 
selfdrive/boardd/boardd.cc