Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 1 | |
| 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 Mierle | 4d11a12 | 2024-07-25 17:50:02 +0000 | [diff] [blame] | 20 | namespace sense { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 21 | namespace { |
| 22 | |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 23 | pubsub_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 | |
| 31 | LedValue LedValueFromProto(const pubsub_LedValue& proto) { |
| 32 | return LedValue(proto.r, proto.g, proto.b); |
| 33 | } |
| 34 | |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 35 | pubsub_Event EventToProto(const Event& event) { |
| 36 | pubsub_Event proto = pubsub_Event_init_default; |
| 37 | |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 38 | if (std::holds_alternative<AlarmStateChange>(event)) { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 39 | proto.which_type = pubsub_Event_alarm_tag; |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 40 | proto.type.alarm = std::get<AlarmStateChange>(event).alarm; |
| 41 | } else if (std::holds_alternative<ButtonA>(event)) { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 42 | proto.which_type = pubsub_Event_button_a_pressed_tag; |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 43 | proto.type.button_a_pressed = std::get<ButtonA>(event).pressed(); |
| 44 | } else if (std::holds_alternative<ButtonB>(event)) { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 45 | proto.which_type = pubsub_Event_button_b_pressed_tag; |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 46 | proto.type.button_b_pressed = std::get<ButtonB>(event).pressed(); |
| 47 | } else if (std::holds_alternative<ButtonX>(event)) { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 48 | proto.which_type = pubsub_Event_button_x_pressed_tag; |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 49 | proto.type.button_x_pressed = std::get<ButtonX>(event).pressed(); |
| 50 | } else if (std::holds_alternative<ButtonY>(event)) { |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 51 | proto.which_type = pubsub_Event_button_y_pressed_tag; |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 52 | 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 Green | b0ca10f | 2024-07-25 21:59:27 +0000 | [diff] [blame^] | 65 | } 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 Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 69 | } 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 Hepler | 18d0eda | 2024-07-17 17:59:42 +0000 | [diff] [blame] | 72 | } 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 Green | b0ca10f | 2024-07-25 21:59:27 +0000 | [diff] [blame^] | 75 | } 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 Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 78 | } else { |
| 79 | PW_LOG_WARN("Unimplemented pubsub service event"); |
| 80 | } |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 81 | return proto; |
| 82 | } |
| 83 | |
| 84 | pw::Result<Event> ProtoToEvent(const pubsub_Event& proto) { |
| 85 | switch (proto.which_type) { |
| 86 | case pubsub_Event_alarm_tag: |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 87 | return AlarmStateChange{.alarm = proto.type.alarm}; |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 88 | case pubsub_Event_button_a_pressed_tag: |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 89 | return ButtonA(proto.type.button_a_pressed); |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 90 | case pubsub_Event_button_b_pressed_tag: |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 91 | return ButtonB(proto.type.button_b_pressed); |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 92 | case pubsub_Event_button_x_pressed_tag: |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 93 | return ButtonX(proto.type.button_x_pressed); |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 94 | case pubsub_Event_button_y_pressed_tag: |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 95 | 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 Green | b0ca10f | 2024-07-25 21:59:27 +0000 | [diff] [blame^] | 105 | case pubsub_Event_led_value_air_quality_tag: |
| 106 | return LedValueAirQualityMode( |
| 107 | LedValueFromProto(proto.type.led_value_air_quality)); |
Erik Gilling | 106fd59 | 2024-07-16 23:49:15 +0000 | [diff] [blame] | 108 | case pubsub_Event_proximity_tag: |
| 109 | return ProximityStateChange{.proximity = proto.type.proximity}; |
Aaron Green | b0ca10f | 2024-07-25 21:59:27 +0000 | [diff] [blame^] | 110 | case pubsub_Event_air_quality_tag: |
| 111 | return AirQuality{.score = static_cast<uint16_t>(proto.type.air_quality)}; |
Alexei Frolov | 90980ad | 2024-07-16 21:26:21 +0000 | [diff] [blame] | 112 | default: |
| 113 | return pw::Status::Unimplemented(); |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | } // namespace |
| 118 | |
| 119 | void PubSubService::Init(PubSub& pubsub) { |
| 120 | pubsub_ = &pubsub; |
| 121 | |
| 122 | pubsub_->Subscribe( |
| 123 | [this](Event event) { stream_.Write(EventToProto(event)); }); |
| 124 | } |
| 125 | |
| 126 | pw::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 | |
| 142 | void 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 Mierle | 4d11a12 | 2024-07-25 17:50:02 +0000 | [diff] [blame] | 149 | } // namespace sense |