| // 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/air_sensor/service.h" |
| |
| #include "pw_assert/check.h" |
| #include "pw_log/log.h" |
| |
| namespace sense { |
| |
| void AirSensorService::Init(Worker& worker, AirSensor& air_sensor) { |
| worker_ = &worker; |
| air_sensor_ = &air_sensor; |
| } |
| |
| void AirSensorService::FillMeasurement(air_sensor_Measurement& response) { |
| response.temperature = air_sensor_->temperature(); |
| response.pressure = air_sensor_->pressure(); |
| response.humidity = air_sensor_->humidity(); |
| response.gas_resistance = air_sensor_->gas_resistance(); |
| response.score = air_sensor_->score(); |
| } |
| |
| pw::Status AirSensorService::Measure(const pw_protobuf_Empty&, |
| air_sensor_Measurement& response) { |
| PW_TRY(air_sensor_->Measure(notification_)); |
| notification_.acquire(); |
| FillMeasurement(response); |
| return pw::OkStatus(); |
| } |
| |
| void AirSensorService::MeasureStream( |
| const air_sensor_MeasureStreamRequest& request, |
| ServerWriter<air_sensor_Measurement>& writer) { |
| if (request.sample_interval_ms < 500) { |
| if (const auto status = writer.Finish(pw::Status::InvalidArgument()); |
| !status.ok()) { |
| PW_LOG_ERROR("Failed to write response: %s", status.str()); |
| } |
| return; |
| } |
| |
| sample_interval_ = pw::chrono::SystemClock::for_at_least( |
| std::chrono::milliseconds(request.sample_interval_ms)); |
| sample_writer_ = std::move(writer); |
| |
| ScheduleSample(); |
| } |
| |
| pw::Status AirSensorService::LogMetrics(const pw_protobuf_Empty&, |
| pw_protobuf_Empty&) { |
| air_sensor_->LogMetrics(); |
| return pw::OkStatus(); |
| } |
| |
| void AirSensorService::SampleCallback(pw::chrono::SystemClock::time_point) { |
| air_sensor_Measurement response; |
| |
| FillMeasurement(response); |
| |
| pw::Status status = sample_writer_.Write(response); |
| if (status.ok()) { |
| ScheduleSample(); |
| } else { |
| PW_LOG_INFO("Air Sensor stream closed; ending periodic sampling"); |
| } |
| } |
| |
| void AirSensorService::ScheduleSample() { |
| worker_->RunOnce([this]() { sample_timer_.InvokeAfter(sample_interval_); }); |
| } |
| |
| } // namespace sense |