blob: ed499257729b2ba8516b2fe401e8a7e82aa0bcce [file] [log] [blame]
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#include "modules/state_manager/state_manager.h"
#include "pw_assert/check.h"
#include "pw_log/log.h"
#include "pw_string/format.h"
namespace sense {
void StateManager::Init() {
pubsub_->Subscribe([this](Event event) { Update(event); });
}
void StateManager::Update(Event event) {
switch (static_cast<EventType>(event.index())) {
case kAirQuality:
last_air_quality_score_ = std::get<AirQuality>(event).score;
break;
case kAlarmStateChange:
state_.get().AlarmStateChanged(std::get<AlarmStateChange>(event).alarm);
break;
case kButtonA:
HandleButtonPress(std::get<ButtonA>(event).pressed(),
&State::ButtonAReleased);
break;
case kButtonB:
HandleButtonPress(std::get<ButtonB>(event).pressed(),
&State::ButtonBReleased);
break;
case kButtonX:
HandleButtonPress(std::get<ButtonX>(event).pressed(),
&State::ButtonXReleased);
break;
case kButtonY:
HandleButtonPress(std::get<ButtonY>(event).pressed(),
&State::ButtonYReleased);
break;
case kLedValueColorRotationMode:
state_.get().ColorRotationModeLedValue(
std::get<LedValueColorRotationMode>(event));
break;
case kLedValueProximityMode:
state_.get().ProximityModeLedValue(
std::get<LedValueProximityMode>(event));
break;
case kLedValueAirQualityMode:
state_.get().AirQualityModeLedValue(
std::get<LedValueAirQualityMode>(event));
break;
case kDemoModeTimerExpired:
state_.get().DemoModeTimerExpired();
break;
case kMorseCodeValue:
state_.get().MorseCodeEdge(std::get<MorseCodeValue>(event));
break;
case kAlarmSilenceRequest:
case kAirQualityThreshold:
case kMorseEncodeRequest:
case kProximityStateChange:
case kProximitySample:
break; // ignore these events
}
}
void StateManager::HandleButtonPress(bool pressed, void (State::* function)()) {
if (pressed) {
led_.Override(0xffffff, 255); // Bright white while pressed.
} else {
led_.EndOverride();
(state_.get().*function)();
}
}
void StateManager::StartMorseReadout(bool repeat) {
pw::Status status = pw::string::FormatOverwrite(
air_quality_score_string_, "%hu", last_air_quality_score_);
PW_CHECK_OK(status);
pubsub_->Publish(MorseEncodeRequest{.message = air_quality_score_string_,
.repeat = repeat ? 0u : 1u});
}
void StateManager::DisplayThreshold() {
led_.SetColor(AirSensor::GetLedValue(current_threshold_));
}
void StateManager::IncrementThreshold(
pw::chrono::SystemClock::duration timeout) {
demo_mode_timer_.Cancel();
uint16_t candidate_threshold = current_threshold_ + kThresholdIncrement;
current_threshold_ = candidate_threshold < kMaxThreshold ? candidate_threshold : kMaxThreshold;
pubsub_->Publish(AirQualityThreshold{
.alarm = current_threshold_,
.silence = static_cast<uint16_t>(current_threshold_ + kThresholdIncrement),
});
DisplayThreshold();
demo_mode_timer_.InvokeAfter(timeout);
}
void StateManager::DecrementThreshold(
pw::chrono::SystemClock::duration timeout) {
demo_mode_timer_.Cancel();
if (current_threshold_ > 0) {
current_threshold_ -= kThresholdIncrement;
}
pubsub_->Publish(AirQualityThreshold{
.alarm = current_threshold_,
.silence = static_cast<uint16_t>(current_threshold_ + kThresholdIncrement),
});
DisplayThreshold();
demo_mode_timer_.InvokeAfter(timeout);
}
void StateManager::LogStateChange(const char* old_state) const {
PW_LOG_INFO("StateManager: %s -> %s", old_state, state_.get().name());
}
} // namespace sense