blob: d69c0f63de7d58560810dea980e7ee624346fad4 [file] [log] [blame]
Alexei Frolov90980ad2024-07-16 21:26:21 +00001
2// Copyright 2024 The Pigweed Authors
3//
4// Licensed under the Apache License, Version 2.0 (the "License"); you may not
5// use this file except in compliance with the License. You may obtain a copy of
6// the License at
7//
8// https://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13// License for the specific language governing permissions and limitations under
14// the License.
15
16#include "modules/pubsub/service.h"
17
18#include "pw_log/log.h"
19
Keir Mierle4d11a122024-07-25 17:50:02 +000020namespace sense {
Alexei Frolov90980ad2024-07-16 21:26:21 +000021namespace {
22
Erik Gilling106fd592024-07-16 23:49:15 +000023pubsub_LedValue LedValueToProto(const LedValue& value) {
24 pubsub_LedValue proto;
25 proto.r = value.r();
26 proto.g = value.g();
27 proto.b = value.b();
28 return proto;
29}
30
31LedValue LedValueFromProto(const pubsub_LedValue& proto) {
32 return LedValue(proto.r, proto.g, proto.b);
33}
34
Alexei Frolov90980ad2024-07-16 21:26:21 +000035pubsub_Event EventToProto(const Event& event) {
36 pubsub_Event proto = pubsub_Event_init_default;
37
Erik Gilling106fd592024-07-16 23:49:15 +000038 if (std::holds_alternative<AlarmStateChange>(event)) {
Alexei Frolov90980ad2024-07-16 21:26:21 +000039 proto.which_type = pubsub_Event_alarm_tag;
Erik Gilling106fd592024-07-16 23:49:15 +000040 proto.type.alarm = std::get<AlarmStateChange>(event).alarm;
41 } else if (std::holds_alternative<ButtonA>(event)) {
Alexei Frolov90980ad2024-07-16 21:26:21 +000042 proto.which_type = pubsub_Event_button_a_pressed_tag;
Erik Gilling106fd592024-07-16 23:49:15 +000043 proto.type.button_a_pressed = std::get<ButtonA>(event).pressed();
44 } else if (std::holds_alternative<ButtonB>(event)) {
Alexei Frolov90980ad2024-07-16 21:26:21 +000045 proto.which_type = pubsub_Event_button_b_pressed_tag;
Erik Gilling106fd592024-07-16 23:49:15 +000046 proto.type.button_b_pressed = std::get<ButtonB>(event).pressed();
47 } else if (std::holds_alternative<ButtonX>(event)) {
Alexei Frolov90980ad2024-07-16 21:26:21 +000048 proto.which_type = pubsub_Event_button_x_pressed_tag;
Erik Gilling106fd592024-07-16 23:49:15 +000049 proto.type.button_x_pressed = std::get<ButtonX>(event).pressed();
50 } else if (std::holds_alternative<ButtonY>(event)) {
Alexei Frolov90980ad2024-07-16 21:26:21 +000051 proto.which_type = pubsub_Event_button_y_pressed_tag;
Erik Gilling106fd592024-07-16 23:49:15 +000052 proto.type.button_y_pressed = std::get<ButtonY>(event).pressed();
53 } else if (std::holds_alternative<LedValueColorRotationMode>(event)) {
54 proto.which_type = pubsub_Event_led_value_color_rotation_tag;
55 proto.type.led_value_color_rotation =
56 LedValueToProto(std::get<LedValueColorRotationMode>(event));
57 } else if (std::holds_alternative<LedValueMorseCodeMode>(event)) {
58 proto.which_type = pubsub_Event_led_value_morse_code_tag;
59 proto.type.led_value_morse_code =
60 LedValueToProto(std::get<LedValueMorseCodeMode>(event));
61 } else if (std::holds_alternative<LedValueProximityMode>(event)) {
62 proto.which_type = pubsub_Event_led_value_proximity_tag;
63 proto.type.led_value_proximity =
64 LedValueToProto(std::get<LedValueProximityMode>(event));
Aaron Greenb0ca10f2024-07-25 21:59:27 +000065 } else if (std::holds_alternative<LedValueAirQualityMode>(event)) {
66 proto.which_type = pubsub_Event_led_value_air_quality_tag;
67 proto.type.led_value_air_quality =
68 LedValueToProto(std::get<LedValueAirQualityMode>(event));
Erik Gilling106fd592024-07-16 23:49:15 +000069 } else if (std::holds_alternative<ProximityStateChange>(event)) {
70 proto.which_type = pubsub_Event_proximity_tag;
71 proto.type.proximity = std::get<ProximityStateChange>(event).proximity;
Wyatt Hepler18d0eda2024-07-17 17:59:42 +000072 } else if (std::holds_alternative<ProximitySample>(event)) {
73 proto.which_type = pubsub_Event_proximity_level_tag;
74 proto.type.proximity_level = std::get<ProximitySample>(event).sample;
Aaron Greenb0ca10f2024-07-25 21:59:27 +000075 } else if (std::holds_alternative<AirQuality>(event)) {
76 proto.which_type = pubsub_Event_air_quality_tag;
77 proto.type.air_quality = std::get<AirQuality>(event).score;
Alexei Frolov90980ad2024-07-16 21:26:21 +000078 } else {
79 PW_LOG_WARN("Unimplemented pubsub service event");
80 }
Alexei Frolov90980ad2024-07-16 21:26:21 +000081 return proto;
82}
83
84pw::Result<Event> ProtoToEvent(const pubsub_Event& proto) {
85 switch (proto.which_type) {
86 case pubsub_Event_alarm_tag:
Erik Gilling106fd592024-07-16 23:49:15 +000087 return AlarmStateChange{.alarm = proto.type.alarm};
Alexei Frolov90980ad2024-07-16 21:26:21 +000088 case pubsub_Event_button_a_pressed_tag:
Erik Gilling106fd592024-07-16 23:49:15 +000089 return ButtonA(proto.type.button_a_pressed);
Alexei Frolov90980ad2024-07-16 21:26:21 +000090 case pubsub_Event_button_b_pressed_tag:
Erik Gilling106fd592024-07-16 23:49:15 +000091 return ButtonB(proto.type.button_b_pressed);
Alexei Frolov90980ad2024-07-16 21:26:21 +000092 case pubsub_Event_button_x_pressed_tag:
Erik Gilling106fd592024-07-16 23:49:15 +000093 return ButtonX(proto.type.button_x_pressed);
Alexei Frolov90980ad2024-07-16 21:26:21 +000094 case pubsub_Event_button_y_pressed_tag:
Erik Gilling106fd592024-07-16 23:49:15 +000095 return ButtonY(proto.type.button_y_pressed);
96 case pubsub_Event_led_value_color_rotation_tag:
97 return LedValueColorRotationMode(
98 LedValueFromProto(proto.type.led_value_color_rotation));
99 case pubsub_Event_led_value_morse_code_tag:
100 return LedValueMorseCodeMode(
101 LedValueFromProto(proto.type.led_value_morse_code));
102 case pubsub_Event_led_value_proximity_tag:
103 return LedValueProximityMode(
104 LedValueFromProto(proto.type.led_value_proximity));
Aaron Greenb0ca10f2024-07-25 21:59:27 +0000105 case pubsub_Event_led_value_air_quality_tag:
106 return LedValueAirQualityMode(
107 LedValueFromProto(proto.type.led_value_air_quality));
Erik Gilling106fd592024-07-16 23:49:15 +0000108 case pubsub_Event_proximity_tag:
109 return ProximityStateChange{.proximity = proto.type.proximity};
Aaron Greenb0ca10f2024-07-25 21:59:27 +0000110 case pubsub_Event_air_quality_tag:
111 return AirQuality{.score = static_cast<uint16_t>(proto.type.air_quality)};
Alexei Frolov90980ad2024-07-16 21:26:21 +0000112 default:
113 return pw::Status::Unimplemented();
114 }
115}
116
117} // namespace
118
119void PubSubService::Init(PubSub& pubsub) {
120 pubsub_ = &pubsub;
121
122 pubsub_->Subscribe(
123 [this](Event event) { stream_.Write(EventToProto(event)); });
124}
125
126pw::Status PubSubService::Publish(const pubsub_Event& request,
127 pw_protobuf_Empty& /*response*/) {
128 pw::Result<Event> maybe_event = ProtoToEvent(request);
129 if (!maybe_event.ok()) {
130 return maybe_event.status();
131 }
132
133 if (pubsub_ != nullptr) {
134 bool published = pubsub_->Publish(*maybe_event);
135 PW_LOG_INFO("%s event to pubsub system",
136 published ? "Published" : "Failed to publish");
137 }
138
139 return pw::OkStatus();
140}
141
142void PubSubService::Subscribe(const pw_protobuf_Empty&,
143 ServerWriter<pubsub_Event>& writer) {
144 PW_LOG_INFO("Streaming pubsub events over RPC channel %u",
145 writer.channel_id());
146 stream_ = std::move(writer);
147}
148
Keir Mierle4d11a122024-07-25 17:50:02 +0000149} // namespace sense