mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Add code to send/receive GoBox infrared control messages. (#7554)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		| @@ -929,6 +929,49 @@ async def pronto_action(var, config, args): | |||||||
|     cg.add(var.set_data(template_)) |     cg.add(var.set_data(template_)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | # Gobox | ||||||
|  | ( | ||||||
|  |     GoboxData, | ||||||
|  |     GoboxBinarySensor, | ||||||
|  |     GoboxTrigger, | ||||||
|  |     GoboxAction, | ||||||
|  |     GoboxDumper, | ||||||
|  | ) = declare_protocol("Gobox") | ||||||
|  | GOBOX_SCHEMA = cv.Schema( | ||||||
|  |     { | ||||||
|  |         cv.Required(CONF_CODE): cv.int_, | ||||||
|  |     } | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @register_binary_sensor("gobox", GoboxBinarySensor, GOBOX_SCHEMA) | ||||||
|  | def gobox_binary_sensor(var, config): | ||||||
|  |     cg.add( | ||||||
|  |         var.set_data( | ||||||
|  |             cg.StructInitializer( | ||||||
|  |                 GoboxData, | ||||||
|  |                 ("code", config[CONF_CODE]), | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |     ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @register_trigger("gobox", GoboxTrigger, GoboxData) | ||||||
|  | def gobox_trigger(var, config): | ||||||
|  |     pass | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @register_dumper("gobox", GoboxDumper) | ||||||
|  | def gobox_dumper(var, config): | ||||||
|  |     pass | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @register_action("gobox", GoboxAction, GOBOX_SCHEMA) | ||||||
|  | async def gobox_action(var, config, args): | ||||||
|  |     template_ = await cg.templatable(config[CONF_CODE], args, cg.int_) | ||||||
|  |     cg.add(var.set_code(template_)) | ||||||
|  |  | ||||||
|  |  | ||||||
| # Roomba | # Roomba | ||||||
| ( | ( | ||||||
|     RoombaData, |     RoombaData, | ||||||
|   | |||||||
							
								
								
									
										131
									
								
								esphome/components/remote_base/gobox_protocol.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								esphome/components/remote_base/gobox_protocol.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | |||||||
|  | #include "gobox_protocol.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace remote_base { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "remote.gobox"; | ||||||
|  |  | ||||||
|  | constexpr uint32_t BIT_MARK_US = 580;  // 70us seems like a safe time delta for the receiver... | ||||||
|  | constexpr uint32_t BIT_ONE_SPACE_US = 1640; | ||||||
|  | constexpr uint32_t BIT_ZERO_SPACE_US = 545; | ||||||
|  | constexpr uint64_t HEADER = 0b011001001100010uL;  // 15 bits | ||||||
|  | constexpr uint64_t HEADER_SIZE = 15; | ||||||
|  | constexpr uint64_t CODE_SIZE = 17; | ||||||
|  |  | ||||||
|  | void GoboxProtocol::dump_timings_(const RawTimings &timings) const { | ||||||
|  |   ESP_LOGD(TAG, "Gobox: size=%u", timings.size()); | ||||||
|  |   for (int32_t timing : timings) { | ||||||
|  |     ESP_LOGD(TAG, "Gobox: timing=%ld", (long) timing); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GoboxProtocol::encode(RemoteTransmitData *dst, const GoboxData &data) { | ||||||
|  |   ESP_LOGI(TAG, "Send Gobox: code=0x%x", data.code); | ||||||
|  |   dst->set_carrier_frequency(38000); | ||||||
|  |   dst->reserve((HEADER_SIZE + CODE_SIZE + 1) * 2); | ||||||
|  |   uint64_t code = (HEADER << CODE_SIZE) | (data.code & ((1UL << CODE_SIZE) - 1)); | ||||||
|  |   ESP_LOGI(TAG, "Send Gobox: code=0x%Lx", code); | ||||||
|  |   for (int16_t i = (HEADER_SIZE + CODE_SIZE - 1); i >= 0; i--) { | ||||||
|  |     if (code & ((uint64_t) 1 << i)) { | ||||||
|  |       dst->item(BIT_MARK_US, BIT_ONE_SPACE_US); | ||||||
|  |     } else { | ||||||
|  |       dst->item(BIT_MARK_US, BIT_ZERO_SPACE_US); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   dst->item(BIT_MARK_US, 2000); | ||||||
|  |  | ||||||
|  |   dump_timings_(dst->get_data()); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | optional<GoboxData> GoboxProtocol::decode(RemoteReceiveData src) { | ||||||
|  |   if (src.size() < ((HEADER_SIZE + CODE_SIZE) * 2 + 1)) { | ||||||
|  |     return {}; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // First check for the header | ||||||
|  |   uint64_t code = HEADER; | ||||||
|  |   for (int16_t i = HEADER_SIZE - 1; i >= 0; i--) { | ||||||
|  |     if (code & ((uint64_t) 1 << i)) { | ||||||
|  |       if (!src.expect_item(BIT_MARK_US, BIT_ONE_SPACE_US)) { | ||||||
|  |         return {}; | ||||||
|  |       } | ||||||
|  |     } else { | ||||||
|  |       if (!src.expect_item(BIT_MARK_US, BIT_ZERO_SPACE_US)) { | ||||||
|  |         return {}; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Next, build up the code | ||||||
|  |   code = 0UL; | ||||||
|  |   for (int16_t i = CODE_SIZE - 1; i >= 0; i--) { | ||||||
|  |     if (!src.expect_mark(BIT_MARK_US)) { | ||||||
|  |       return {}; | ||||||
|  |     } | ||||||
|  |     if (src.expect_space(BIT_ONE_SPACE_US)) { | ||||||
|  |       code |= (1UL << i); | ||||||
|  |     } else if (!src.expect_space(BIT_ZERO_SPACE_US)) { | ||||||
|  |       return {}; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   if (!src.expect_mark(BIT_MARK_US)) { | ||||||
|  |     return {}; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   dump_timings_(src.get_raw_data()); | ||||||
|  |  | ||||||
|  |   GoboxData out; | ||||||
|  |   out.code = code; | ||||||
|  |  | ||||||
|  |   return out; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void GoboxProtocol::dump(const GoboxData &data) { | ||||||
|  |   ESP_LOGI(TAG, "Received Gobox: code=0x%x", data.code); | ||||||
|  |   switch (data.code) { | ||||||
|  |     case GOBOX_MENU: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=MENU"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_RETURN: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=RETURN"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_UP: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=UP"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_LEFT: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=LEFT"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_RIGHT: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=RIGHT"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_DOWN: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=DOWN"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_OK: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=OK"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_TOGGLE: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=TOGGLE"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_PROFILE: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=PROFILE"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_FASTER: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=FASTER"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_SLOWER: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=SLOWER"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_LOUDER: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=LOUDER"); | ||||||
|  |       break; | ||||||
|  |     case GOBOX_SOFTER: | ||||||
|  |       ESP_LOGI(TAG, "Received Gobox: key=SOFTER"); | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace remote_base | ||||||
|  | }  // namespace esphome | ||||||
							
								
								
									
										54
									
								
								esphome/components/remote_base/gobox_protocol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								esphome/components/remote_base/gobox_protocol.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/component.h" | ||||||
|  | #include "remote_base.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace remote_base { | ||||||
|  |  | ||||||
|  | struct GoboxData { | ||||||
|  |   int code; | ||||||
|  |   bool operator==(const GoboxData &rhs) const { return code == rhs.code; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | enum { | ||||||
|  |   GOBOX_MENU = 0xaa55, | ||||||
|  |   GOBOX_RETURN = 0x22dd, | ||||||
|  |   GOBOX_UP = 0x0af5, | ||||||
|  |   GOBOX_LEFT = 0x8a75, | ||||||
|  |   GOBOX_RIGHT = 0x48b7, | ||||||
|  |   GOBOX_DOWN = 0xa25d, | ||||||
|  |   GOBOX_OK = 0xc837, | ||||||
|  |   GOBOX_TOGGLE = 0xb847, | ||||||
|  |   GOBOX_PROFILE = 0xfa05, | ||||||
|  |   GOBOX_FASTER = 0xf00f, | ||||||
|  |   GOBOX_SLOWER = 0xd02f, | ||||||
|  |   GOBOX_LOUDER = 0xb04f, | ||||||
|  |   GOBOX_SOFTER = 0xf807, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | class GoboxProtocol : public RemoteProtocol<GoboxData> { | ||||||
|  |  private: | ||||||
|  |   void dump_timings_(const RawTimings &timings) const; | ||||||
|  |  | ||||||
|  |  public: | ||||||
|  |   void encode(RemoteTransmitData *dst, const GoboxData &data) override; | ||||||
|  |   optional<GoboxData> decode(RemoteReceiveData src) override; | ||||||
|  |   void dump(const GoboxData &data) override; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | DECLARE_REMOTE_PROTOCOL(Gobox) | ||||||
|  |  | ||||||
|  | template<typename... Ts> class GoboxAction : public RemoteTransmitterActionBase<Ts...> { | ||||||
|  |  public: | ||||||
|  |   TEMPLATABLE_VALUE(uint64_t, code); | ||||||
|  |  | ||||||
|  |   void encode(RemoteTransmitData *dst, Ts... x) override { | ||||||
|  |     GoboxData data{}; | ||||||
|  |     data.code = this->code_.value(x...); | ||||||
|  |     GoboxProtocol().encode(dst, data); | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace remote_base | ||||||
|  | }  // namespace esphome | ||||||
| @@ -48,6 +48,11 @@ on_drayton: | |||||||
|     - logger.log: |     - logger.log: | ||||||
|         format: "on_drayton: %u %u %u" |         format: "on_drayton: %u %u %u" | ||||||
|         args: ["x.address", "x.channel", "x.command"] |         args: ["x.address", "x.channel", "x.command"] | ||||||
|  | on_gobox: | ||||||
|  |   then: | ||||||
|  |     - logger.log: | ||||||
|  |         format: "on_gobox: %d" | ||||||
|  |         args: ["x.code"] | ||||||
| on_jvc: | on_jvc: | ||||||
|   then: |   then: | ||||||
|     - logger.log: |     - logger.log: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user