mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Added CanalSat and CanalSatLD protocol support (#3513)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							7e1e799b3a
						
					
				
				
					commit
					7810ad40d7
				
			| @@ -237,6 +237,107 @@ async def build_dumpers(config): | ||||
|     return dumpers | ||||
|  | ||||
|  | ||||
| # CanalSat | ||||
| ( | ||||
|     CanalSatData, | ||||
|     CanalSatBinarySensor, | ||||
|     CanalSatTrigger, | ||||
|     CanalSatAction, | ||||
|     CanalSatDumper, | ||||
| ) = declare_protocol("CanalSat") | ||||
| CANALSAT_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_DEVICE): cv.hex_uint8_t, | ||||
|         cv.Optional(CONF_ADDRESS, default=0): cv.hex_uint8_t, | ||||
|         cv.Required(CONF_COMMAND): cv.hex_uint8_t, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @register_binary_sensor("canalsat", CanalSatBinarySensor, CANALSAT_SCHEMA) | ||||
| def canalsat_binary_sensor(var, config): | ||||
|     cg.add( | ||||
|         var.set_data( | ||||
|             cg.StructInitializer( | ||||
|                 CanalSatData, | ||||
|                 ("device", config[CONF_DEVICE]), | ||||
|                 ("address", config[CONF_ADDRESS]), | ||||
|                 ("command", config[CONF_COMMAND]), | ||||
|             ) | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| @register_trigger("canalsat", CanalSatTrigger, CanalSatData) | ||||
| def canalsat_trigger(var, config): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| @register_dumper("canalsat", CanalSatDumper) | ||||
| def canalsat_dumper(var, config): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| @register_action("canalsat", CanalSatAction, CANALSAT_SCHEMA) | ||||
| async def canalsat_action(var, config, args): | ||||
|     template_ = await cg.templatable(config[CONF_DEVICE], args, cg.uint8) | ||||
|     cg.add(var.set_device(template_)) | ||||
|     template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint8) | ||||
|     cg.add(var.set_address(template_)) | ||||
|     template_ = await cg.templatable(config[CONF_COMMAND], args, cg.uint8) | ||||
|     cg.add(var.set_command(template_)) | ||||
|  | ||||
|  | ||||
| ( | ||||
|     CanalSatLDData, | ||||
|     CanalSatLDBinarySensor, | ||||
|     CanalSatLDTrigger, | ||||
|     CanalSatLDAction, | ||||
|     CanalSatLDDumper, | ||||
| ) = declare_protocol("CanalSatLD") | ||||
| CANALSATLD_SCHEMA = cv.Schema( | ||||
|     { | ||||
|         cv.Required(CONF_DEVICE): cv.hex_uint8_t, | ||||
|         cv.Optional(CONF_ADDRESS, default=0): cv.hex_uint8_t, | ||||
|         cv.Required(CONF_COMMAND): cv.hex_uint8_t, | ||||
|     } | ||||
| ) | ||||
|  | ||||
|  | ||||
| @register_binary_sensor("canalsatld", CanalSatLDBinarySensor, CANALSAT_SCHEMA) | ||||
| def canalsatld_binary_sensor(var, config): | ||||
|     cg.add( | ||||
|         var.set_data( | ||||
|             cg.StructInitializer( | ||||
|                 CanalSatLDData, | ||||
|                 ("device", config[CONF_DEVICE]), | ||||
|                 ("address", config[CONF_ADDRESS]), | ||||
|                 ("command", config[CONF_COMMAND]), | ||||
|             ) | ||||
|         ) | ||||
|     ) | ||||
|  | ||||
|  | ||||
| @register_trigger("canalsatld", CanalSatLDTrigger, CanalSatLDData) | ||||
| def canalsatld_trigger(var, config): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| @register_dumper("canalsatld", CanalSatLDDumper) | ||||
| def canalsatld_dumper(var, config): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| @register_action("canalsatld", CanalSatLDAction, CANALSATLD_SCHEMA) | ||||
| async def canalsatld_action(var, config, args): | ||||
|     template_ = await cg.templatable(config[CONF_DEVICE], args, cg.uint8) | ||||
|     cg.add(var.set_device(template_)) | ||||
|     template_ = await cg.templatable(config[CONF_ADDRESS], args, cg.uint8) | ||||
|     cg.add(var.set_address(template_)) | ||||
|     template_ = await cg.templatable(config[CONF_COMMAND], args, cg.uint8) | ||||
|     cg.add(var.set_command(template_)) | ||||
|  | ||||
|  | ||||
| # Coolix | ||||
| ( | ||||
|     CoolixData, | ||||
|   | ||||
							
								
								
									
										108
									
								
								esphome/components/remote_base/canalsat_protocol.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								esphome/components/remote_base/canalsat_protocol.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| #include "canalsat_protocol.h" | ||||
| #include "esphome/core/log.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace remote_base { | ||||
|  | ||||
| static const char *const CANALSAT_TAG = "remote.canalsat"; | ||||
| static const char *const CANALSATLD_TAG = "remote.canalsatld"; | ||||
|  | ||||
| static const uint16_t CANALSAT_FREQ = 55500; | ||||
| static const uint16_t CANALSATLD_FREQ = 56000; | ||||
| static const uint16_t CANALSAT_UNIT = 250; | ||||
| static const uint16_t CANALSATLD_UNIT = 320; | ||||
|  | ||||
| CanalSatProtocol::CanalSatProtocol() { | ||||
|   this->frequency_ = CANALSAT_FREQ; | ||||
|   this->unit_ = CANALSAT_UNIT; | ||||
|   this->tag_ = CANALSAT_TAG; | ||||
| } | ||||
|  | ||||
| CanalSatLDProtocol::CanalSatLDProtocol() { | ||||
|   this->frequency_ = CANALSATLD_FREQ; | ||||
|   this->unit_ = CANALSATLD_UNIT; | ||||
|   this->tag_ = CANALSATLD_TAG; | ||||
| } | ||||
|  | ||||
| void CanalSatBaseProtocol::encode(RemoteTransmitData *dst, const CanalSatData &data) { | ||||
|   dst->reserve(48); | ||||
|   dst->set_carrier_frequency(this->frequency_); | ||||
|  | ||||
|   uint32_t raw{ | ||||
|       static_cast<uint32_t>((1 << 23) | (data.device << 16) | (data.address << 10) | (0 << 9) | (data.command << 1))}; | ||||
|   bool was_high{true}; | ||||
|  | ||||
|   for (uint32_t mask = 0x800000; mask; mask >>= 1) { | ||||
|     if (raw & mask) { | ||||
|       if (was_high) { | ||||
|         dst->mark(this->unit_); | ||||
|       } | ||||
|       was_high = true; | ||||
|       if (raw & mask >> 1) { | ||||
|         dst->space(this->unit_); | ||||
|       } else { | ||||
|         dst->space(this->unit_ * 2); | ||||
|       } | ||||
|     } else { | ||||
|       if (!was_high) { | ||||
|         dst->space(this->unit_); | ||||
|       } | ||||
|       was_high = false; | ||||
|       if (raw & mask >> 1) { | ||||
|         dst->mark(this->unit_ * 2); | ||||
|       } else { | ||||
|         dst->mark(this->unit_); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| optional<CanalSatData> CanalSatBaseProtocol::decode(RemoteReceiveData src) { | ||||
|   CanalSatData data{ | ||||
|       .device = 0, | ||||
|       .address = 0, | ||||
|       .repeat = 0, | ||||
|       .command = 0, | ||||
|   }; | ||||
|  | ||||
|   // Check if initial mark and spaces match | ||||
|   if (!src.peek_mark(this->unit_) || !(src.peek_space(this->unit_, 1) || src.peek_space(this->unit_ * 2, 1))) { | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   uint8_t bit{1}; | ||||
|   uint8_t offset{1}; | ||||
|   uint32_t buffer{0}; | ||||
|  | ||||
|   while (offset < 24) { | ||||
|     buffer = buffer | (bit << (24 - offset++)); | ||||
|     src.advance(); | ||||
|     if (src.peek_mark(this->unit_) || src.peek_space(this->unit_)) { | ||||
|       src.advance(); | ||||
|     } else if (src.peek_mark(this->unit_ * 2) || src.peek_space(this->unit_ * 2)) { | ||||
|       bit = !bit; | ||||
|     } else if (offset != 24 && bit != 1) {  // If last bit is high, final space is indistinguishable | ||||
|       return {}; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   data.device = (0xFF0000 & buffer) >> 16; | ||||
|   data.address = (0x00FF00 & buffer) >> 10; | ||||
|   data.repeat = (0x00FF00 & buffer) >> 9; | ||||
|   data.command = (0x0000FF & buffer) >> 1; | ||||
|  | ||||
|   return data; | ||||
| } | ||||
|  | ||||
| void CanalSatBaseProtocol::dump(const CanalSatData &data) { | ||||
|   if (this->tag_ == CANALSATLD_TAG) { | ||||
|     ESP_LOGD(this->tag_, "Received CanalSatLD: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, | ||||
|              data.address, data.command, data.repeat); | ||||
|   } else { | ||||
|     ESP_LOGD(this->tag_, "Received CanalSat: device=0x%02X, address=0x%02X, command=0x%02X, repeat=0x%X", data.device, | ||||
|              data.address, data.command, data.repeat); | ||||
|   } | ||||
| } | ||||
|  | ||||
| }  // namespace remote_base | ||||
| }  // namespace esphome | ||||
							
								
								
									
										78
									
								
								esphome/components/remote_base/canalsat_protocol.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								esphome/components/remote_base/canalsat_protocol.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "remote_base.h" | ||||
|  | ||||
| namespace esphome { | ||||
| namespace remote_base { | ||||
|  | ||||
| struct CanalSatData { | ||||
|   uint8_t device : 7; | ||||
|   uint8_t address : 6; | ||||
|   uint8_t repeat : 1; | ||||
|   uint8_t command : 7; | ||||
|  | ||||
|   bool operator==(const CanalSatData &rhs) const { | ||||
|     return device == rhs.device && address == rhs.address && command == rhs.command; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct CanalSatLDData : public CanalSatData {}; | ||||
|  | ||||
| class CanalSatBaseProtocol : public RemoteProtocol<CanalSatData> { | ||||
|  public: | ||||
|   void encode(RemoteTransmitData *dst, const CanalSatData &data) override; | ||||
|   optional<CanalSatData> decode(RemoteReceiveData src) override; | ||||
|   void dump(const CanalSatData &data) override; | ||||
|  | ||||
|  protected: | ||||
|   uint16_t frequency_; | ||||
|   uint16_t unit_; | ||||
|   const char *tag_; | ||||
| }; | ||||
|  | ||||
| class CanalSatProtocol : public CanalSatBaseProtocol { | ||||
|  public: | ||||
|   CanalSatProtocol(); | ||||
| }; | ||||
|  | ||||
| class CanalSatLDProtocol : public CanalSatBaseProtocol { | ||||
|  public: | ||||
|   CanalSatLDProtocol(); | ||||
| }; | ||||
|  | ||||
| DECLARE_REMOTE_PROTOCOL(CanalSat) | ||||
|  | ||||
| template<typename... Ts> class CanalSatAction : public RemoteTransmitterActionBase<Ts...> { | ||||
|  public: | ||||
|   TEMPLATABLE_VALUE(uint8_t, device) | ||||
|   TEMPLATABLE_VALUE(uint8_t, address) | ||||
|   TEMPLATABLE_VALUE(uint8_t, command) | ||||
|  | ||||
|   void encode(RemoteTransmitData *dst, Ts... x) { | ||||
|     CanalSatData data{}; | ||||
|     data.device = this->device_.value(x...); | ||||
|     data.address = this->address_.value(x...); | ||||
|     data.command = this->command_.value(x...); | ||||
|     CanalSatProtocol().encode(dst, data); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| DECLARE_REMOTE_PROTOCOL(CanalSatLD) | ||||
|  | ||||
| template<typename... Ts> class CanalSatLDAction : public RemoteTransmitterActionBase<Ts...> { | ||||
|  public: | ||||
|   TEMPLATABLE_VALUE(uint8_t, device) | ||||
|   TEMPLATABLE_VALUE(uint8_t, address) | ||||
|   TEMPLATABLE_VALUE(uint8_t, command) | ||||
|  | ||||
|   void encode(RemoteTransmitData *dst, Ts... x) { | ||||
|     CanalSatData data{}; | ||||
|     data.device = this->device_.value(x...); | ||||
|     data.address = this->address_.value(x...); | ||||
|     data.command = this->command_.value(x...); | ||||
|     CanalSatLDProtocol().encode(dst, data); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| }  // namespace remote_base | ||||
| }  // namespace esphome | ||||
		Reference in New Issue
	
	Block a user