mirror of
				https://github.com/esphome/esphome.git
				synced 2025-11-03 08:31:47 +00:00 
			
		
		
		
	Compare commits
	
		
			1321 Commits
		
	
	
		
			2021.11.0b
			...
			2022.12.0b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d9563d4de1 | ||
| 
						 | 
					cc7e2bf8db | ||
| 
						 | 
					5d98e2923b | ||
| 
						 | 
					07197d12f6 | ||
| 
						 | 
					7b0a298497 | ||
| 
						 | 
					21679cf2ba | ||
| 
						 | 
					4be7cd12a1 | ||
| 
						 | 
					dee4d0ccb7 | ||
| 
						 | 
					c6885c1bf4 | ||
| 
						 | 
					8b8efb57af | ||
| 
						 | 
					499e120aa4 | ||
| 
						 | 
					6f198a4736 | ||
| 
						 | 
					f500f448b1 | ||
| 
						 | 
					6ad9baa870 | ||
| 
						 | 
					f843925301 | ||
| 
						 | 
					4a3b628946 | ||
| 
						 | 
					4ffdc38cf5 | ||
| 
						 | 
					f83f1bff19 | ||
| 
						 | 
					9370ff3dfa | ||
| 
						 | 
					2053b02c61 | ||
| 
						 | 
					f34e797a0d | ||
| 
						 | 
					30a2fc1273 | ||
| 
						 | 
					48da5ef1c4 | ||
| 
						 | 
					dbbbba3cf8 | ||
| 
						 | 
					16e523ca68 | ||
| 
						 | 
					3b2bbd306f | ||
| 
						 | 
					54caed36f7 | ||
| 
						 | 
					dfcccda69e | ||
| 
						 | 
					de352c1609 | ||
| 
						 | 
					c30068fc97 | ||
| 
						 | 
					f28f712827 | ||
| 
						 | 
					b63ade298f | ||
| 
						 | 
					f117d4f50a | ||
| 
						 | 
					6e4267b797 | ||
| 
						 | 
					2dd032475b | ||
| 
						 | 
					db0ed055dd | ||
| 
						 | 
					106c1bfac2 | ||
| 
						 | 
					eb2a0f45db | ||
| 
						 | 
					2b4fdd6c39 | ||
| 
						 | 
					3669320398 | ||
| 
						 | 
					d706f40ce1 | ||
| 
						 | 
					027284c29c | ||
| 
						 | 
					c55e01ff3f | ||
| 
						 | 
					a59ce7bfa2 | ||
| 
						 | 
					a6196267c9 | ||
| 
						 | 
					eb664b99ba | ||
| 
						 | 
					8414bb9a7a | ||
| 
						 | 
					ccef7c322f | ||
| 
						 | 
					120327866f | ||
| 
						 | 
					bc5c2d4eb4 | ||
| 
						 | 
					d5ff8f6117 | ||
| 
						 | 
					ad0d6f6337 | ||
| 
						 | 
					873de13b3d | ||
| 
						 | 
					56de8e5cc4 | ||
| 
						 | 
					73c82862cf | ||
| 
						 | 
					75573a3ed1 | ||
| 
						 | 
					1166d93805 | ||
| 
						 | 
					ac112a32c9 | ||
| 
						 | 
					cee45c1221 | ||
| 
						 | 
					fb56b5388e | ||
| 
						 | 
					ed42cefeee | ||
| 
						 | 
					9052947a71 | ||
| 
						 | 
					53e0af18fb | ||
| 
						 | 
					c5f59fad62 | ||
| 
						 | 
					b089a4ea80 | ||
| 
						 | 
					555bba7698 | ||
| 
						 | 
					294901fbe9 | ||
| 
						 | 
					ec576bf9f9 | ||
| 
						 | 
					9273e3775b | ||
| 
						 | 
					ce5cedb466 | ||
| 
						 | 
					b184b01600 | ||
| 
						 | 
					81b4078871 | ||
| 
						 | 
					d067c8f80b | ||
| 
						 | 
					8975b4b3f6 | ||
| 
						 | 
					20da03f8c6 | ||
| 
						 | 
					ef26677b67 | ||
| 
						 | 
					91925b1826 | ||
| 
						 | 
					1f33ad037d | ||
| 
						 | 
					fef60e335e | ||
| 
						 | 
					195c78846f | ||
| 
						 | 
					0f9c956c04 | ||
| 
						 | 
					7258a82875 | ||
| 
						 | 
					c1f696c32a | ||
| 
						 | 
					f2b63d9c67 | ||
| 
						 | 
					7896a7783b | ||
| 
						 | 
					621771e1ee | ||
| 
						 | 
					2b032e8606 | ||
| 
						 | 
					5e1b724697 | ||
| 
						 | 
					e6db61c2f0 | ||
| 
						 | 
					c2e198311c | ||
| 
						 | 
					d874626662 | ||
| 
						 | 
					eead72333e | ||
| 
						 | 
					719c212009 | ||
| 
						 | 
					65030e1c37 | ||
| 
						 | 
					3f88b63920 | ||
| 
						 | 
					70f1c71a9f | ||
| 
						 | 
					816df5ad47 | ||
| 
						 | 
					f7b1602adf | ||
| 
						 | 
					7e88eea532 | ||
| 
						 | 
					d1cdfd3b72 | ||
| 
						 | 
					d6a03d48f5 | ||
| 
						 | 
					d453b42b1a | ||
| 
						 | 
					7c19b961e2 | ||
| 
						 | 
					147b113b62 | ||
| 
						 | 
					d924702825 | ||
| 
						 | 
					e8784ba383 | ||
| 
						 | 
					e3a454d1a6 | ||
| 
						 | 
					392dc8b0db | ||
| 
						 | 
					2f62426f09 | ||
| 
						 | 
					58fda40389 | ||
| 
						 | 
					6a73699a38 | ||
| 
						 | 
					3bd6456fbe | ||
| 
						 | 
					608be4e050 | ||
| 
						 | 
					10f590324b | ||
| 
						 | 
					cb2d9e4bec | ||
| 
						 | 
					9e3ee28744 | ||
| 
						 | 
					472dcebf2c | ||
| 
						 | 
					39f0f748bf | ||
| 
						 | 
					9efe59a984 | ||
| 
						 | 
					fcb02af782 | ||
| 
						 | 
					9f30f53c6b | ||
| 
						 | 
					2f18ae00c5 | ||
| 
						 | 
					27a339fa12 | ||
| 
						 | 
					3aeef1afd4 | ||
| 
						 | 
					a45ee8f4ac | ||
| 
						 | 
					31b62d7dca | ||
| 
						 | 
					22f81475db | ||
| 
						 | 
					cc7cf73d59 | ||
| 
						 | 
					9682e60a25 | ||
| 
						 | 
					2c2e68123a | ||
| 
						 | 
					fcec7d45cb | ||
| 
						 | 
					7c8f502e7e | ||
| 
						 | 
					dc17c47634 | ||
| 
						 | 
					3d927c2f44 | ||
| 
						 | 
					0ae61410d2 | ||
| 
						 | 
					2455589f61 | ||
| 
						 | 
					c6afae0da5 | ||
| 
						 | 
					3155f02be6 | ||
| 
						 | 
					4fa0e860ad | ||
| 
						 | 
					8c122aa372 | ||
| 
						 | 
					5a0bf9fee9 | ||
| 
						 | 
					dc794918ed | ||
| 
						 | 
					02b15dbc4a | ||
| 
						 | 
					ed316b1ce3 | ||
| 
						 | 
					d7858f16c1 | ||
| 
						 | 
					291deb12ad | ||
| 
						 | 
					3e110681c9 | ||
| 
						 | 
					65fbfa2097 | ||
| 
						 | 
					16ebf9da4c | ||
| 
						 | 
					2c76381fcd | ||
| 
						 | 
					90683223dd | ||
| 
						 | 
					de79171815 | ||
| 
						 | 
					1554c5700e | ||
| 
						 | 
					5cf257b251 | ||
| 
						 | 
					04883e14f6 | ||
| 
						 | 
					0a649c184f | ||
| 
						 | 
					0e66c899ce | ||
| 
						 | 
					e7d236f939 | ||
| 
						 | 
					fae4d03473 | ||
| 
						 | 
					fd8b9fb028 | ||
| 
						 | 
					97bd3e7320 | ||
| 
						 | 
					dfca2f88d3 | ||
| 
						 | 
					8cad93de37 | ||
| 
						 | 
					bdf1813b3a | ||
| 
						 | 
					45b6c93f5f | ||
| 
						 | 
					e5b8dd7f2d | ||
| 
						 | 
					a1c8b8092b | ||
| 
						 | 
					109ca2406d | ||
| 
						 | 
					3a689112fd | ||
| 
						 | 
					40e0cd0f03 | ||
| 
						 | 
					bf4d3df906 | ||
| 
						 | 
					0e30c49e3f | ||
| 
						 | 
					e61a01f7bb | ||
| 
						 | 
					f8640cf2cd | ||
| 
						 | 
					4bcfeb6e33 | ||
| 
						 | 
					a5d4ca0f6d | ||
| 
						 | 
					85faecb2fd | ||
| 
						 | 
					991fc54994 | ||
| 
						 | 
					2de891dc32 | ||
| 
						 | 
					9865cb7f55 | ||
| 
						 | 
					f97252b93a | ||
| 
						 | 
					6124531479 | ||
| 
						 | 
					b8549d323c | ||
| 
						 | 
					01adece673 | ||
| 
						 | 
					0220934e4c | ||
| 
						 | 
					ca09693efa | ||
| 
						 | 
					e96d7483b3 | ||
| 
						 | 
					f2c4f018de | ||
| 
						 | 
					237c7dd169 | ||
| 
						 | 
					b781b8d77d | ||
| 
						 | 
					60b7d1c8a1 | ||
| 
						 | 
					8161222b33 | ||
| 
						 | 
					1000c4466f | ||
| 
						 | 
					60717b074e | ||
| 
						 | 
					c3fba97b4c | ||
| 
						 | 
					d93f35701f | ||
| 
						 | 
					702b60ce66 | ||
| 
						 | 
					f8ce597918 | ||
| 
						 | 
					22e0a944c8 | ||
| 
						 | 
					3a134ef009 | ||
| 
						 | 
					96e8cb66b6 | ||
| 
						 | 
					615288c151 | ||
| 
						 | 
					6153bcc6ad | ||
| 
						 | 
					e87edcc77a | ||
| 
						 | 
					a21c3e8e2d | ||
| 
						 | 
					d7576f67e8 | ||
| 
						 | 
					138de643a2 | ||
| 
						 | 
					f30e54d177 | ||
| 
						 | 
					41b5cb06d3 | ||
| 
						 | 
					4ac72d7d08 | ||
| 
						 | 
					06ac4980ba | ||
| 
						 | 
					ccbfa20bb9 | ||
| 
						 | 
					58cd754e07 | ||
| 
						 | 
					d1263e583b | ||
| 
						 | 
					67c911c37f | ||
| 
						 | 
					288e3c3e3e | ||
| 
						 | 
					a84378c6c2 | ||
| 
						 | 
					b6073408f4 | ||
| 
						 | 
					b2d91ac5de | ||
| 
						 | 
					8bf34e09f4 | ||
| 
						 | 
					be914f2c15 | ||
| 
						 | 
					8bb670521d | ||
| 
						 | 
					225b3c1494 | ||
| 
						 | 
					4bf94e0757 | ||
| 
						 | 
					3b21d1d81e | ||
| 
						 | 
					5ec1588110 | ||
| 
						 | 
					71387be72e | ||
| 
						 | 
					98171c9f49 | ||
| 
						 | 
					a6c999dea0 | ||
| 
						 | 
					bf15b1d302 | ||
| 
						 | 
					f422fabab4 | ||
| 
						 | 
					01b130ec59 | ||
| 
						 | 
					48a1797e72 | ||
| 
						 | 
					b34d24735a | ||
| 
						 | 
					fe38b36c26 | ||
| 
						 | 
					03fca8d91e | ||
| 
						 | 
					9f9980e338 | ||
| 
						 | 
					19900b004b | ||
| 
						 | 
					a8ff0a8913 | ||
| 
						 | 
					45861456f1 | ||
| 
						 | 
					44b335e7e3 | ||
| 
						 | 
					de23bbace2 | ||
| 
						 | 
					edff9ae322 | ||
| 
						 | 
					3c2766448d | ||
| 
						 | 
					786c8b6cfe | ||
| 
						 | 
					e8de6a3a67 | ||
| 
						 | 
					3c320c4c83 | ||
| 
						 | 
					3b83f967e4 | ||
| 
						 | 
					5e96b8ef7c | ||
| 
						 | 
					5df0e82c37 | ||
| 
						 | 
					fd57b21aff | ||
| 
						 | 
					6087183a0c | ||
| 
						 | 
					01b7c4200e | ||
| 
						 | 
					7171286c3c | ||
| 
						 | 
					2d58239b74 | ||
| 
						 | 
					6b52f62531 | ||
| 
						 | 
					1001d9c04e | ||
| 
						 | 
					d220d41182 | ||
| 
						 | 
					c3a8972550 | ||
| 
						 | 
					263b603188 | ||
| 
						 | 
					584b722e7e | ||
| 
						 | 
					05edfd0e82 | ||
| 
						 | 
					16249c02a5 | ||
| 
						 | 
					e8ff36d1f3 | ||
| 
						 | 
					ed443c6153 | ||
| 
						 | 
					f4a84765cd | ||
| 
						 | 
					106de3530d | ||
| 
						 | 
					119c3f6f46 | ||
| 
						 | 
					d2c1c7507c | ||
| 
						 | 
					efdb3d1f40 | ||
| 
						 | 
					8095db6715 | ||
| 
						 | 
					ce2e161b08 | ||
| 
						 | 
					9dbc32b85f | ||
| 
						 | 
					66226abb48 | ||
| 
						 | 
					34bef2f2ca | ||
| 
						 | 
					6ef93452f5 | ||
| 
						 | 
					fdd4ca6837 | ||
| 
						 | 
					9655362f23 | ||
| 
						 | 
					130c9fad22 | ||
| 
						 | 
					3de0b601bf | ||
| 
						 | 
					91560ae4e9 | ||
| 
						 | 
					fd6135aebb | ||
| 
						 | 
					68ea59f3ae | ||
| 
						 | 
					e5fe5d1249 | ||
| 
						 | 
					9a69769a7e | ||
| 
						 | 
					63b42f3608 | ||
| 
						 | 
					d56107e97f | ||
| 
						 | 
					33f296e05b | ||
| 
						 | 
					3572c62315 | ||
| 
						 | 
					97e067a277 | ||
| 
						 | 
					1444cddda9 | ||
| 
						 | 
					5f56cf3128 | ||
| 
						 | 
					5c4e83ebdc | ||
| 
						 | 
					91f1c25fcc | ||
| 
						 | 
					47a7a239ae | ||
| 
						 | 
					fb9984e21f | ||
| 
						 | 
					b2db524366 | ||
| 
						 | 
					ab8674a5c7 | ||
| 
						 | 
					d1c85fc3fa | ||
| 
						 | 
					55ad45e3ee | ||
| 
						 | 
					f6e5a8cb2a | ||
| 
						 | 
					7a91ca9809 | ||
| 
						 | 
					71dd04b09e | ||
| 
						 | 
					7deabbb512 | ||
| 
						 | 
					625a575e49 | ||
| 
						 | 
					df4d0da221 | ||
| 
						 | 
					6b23b7cad7 | ||
| 
						 | 
					cea7deab91 | ||
| 
						 | 
					c61abf6aca | ||
| 
						 | 
					917bbc669c | ||
| 
						 | 
					0ac4c055de | ||
| 
						 | 
					78b55d86e9 | ||
| 
						 | 
					aaf50fc2e6 | ||
| 
						 | 
					6a8f4e92df | ||
| 
						 | 
					6d267fda01 | ||
| 
						 | 
					88943103a2 | ||
| 
						 | 
					e557dc7208 | ||
| 
						 | 
					3558806b0e | ||
| 
						 | 
					f1e8cc2cf0 | ||
| 
						 | 
					6236db1a27 | ||
| 
						 | 
					f4b0917239 | ||
| 
						 | 
					a5e3cd1a42 | ||
| 
						 | 
					b3cca5dcb6 | ||
| 
						 | 
					49465223a4 | ||
| 
						 | 
					15f0e54cbf | ||
| 
						 | 
					ed8f343aad | ||
| 
						 | 
					cbd8d70431 | ||
| 
						 | 
					9ff187c3f8 | ||
| 
						 | 
					be473b97c4 | ||
| 
						 | 
					9a5f865eea | ||
| 
						 | 
					790280ace9 | ||
| 
						 | 
					8ba207fc7f | ||
| 
						 | 
					d66b2a1778 | ||
| 
						 | 
					e3f2562047 | ||
| 
						 | 
					f77118a90c | ||
| 
						 | 
					041eb8f6cc | ||
| 
						 | 
					733a84df75 | ||
| 
						 | 
					acd0b50b40 | ||
| 
						 | 
					635851807a | ||
| 
						 | 
					89fd367297 | ||
| 
						 | 
					60e46d485e | ||
| 
						 | 
					5bf0c92318 | ||
| 
						 | 
					39d493c278 | ||
| 
						 | 
					d2ce62aa13 | ||
| 
						 | 
					c8eb30ef27 | ||
| 
						 | 
					c317422ed7 | ||
| 
						 | 
					614eb81ad7 | ||
| 
						 | 
					219c5953f1 | ||
| 
						 | 
					5d712c73ea | ||
| 
						 | 
					7097b7677e | ||
| 
						 | 
					7a4cf13e0c | ||
| 
						 | 
					4788a6182e | ||
| 
						 | 
					e3dad7c632 | ||
| 
						 | 
					1b4156646e | ||
| 
						 | 
					31ad75d01b | ||
| 
						 | 
					aa2eb29274 | ||
| 
						 | 
					22eb4f9cb9 | ||
| 
						 | 
					3acc8e7479 | ||
| 
						 | 
					2650441013 | ||
| 
						 | 
					71697df2b6 | ||
| 
						 | 
					acd55b9601 | ||
| 
						 | 
					0907de8662 | ||
| 
						 | 
					15eb9605a8 | ||
| 
						 | 
					6d5cb866db | ||
| 
						 | 
					768490089e | ||
| 
						 | 
					4d66fab360 | ||
| 
						 | 
					bd6bc283b6 | ||
| 
						 | 
					3120a0ba83 | ||
| 
						 | 
					b2199d5464 | ||
| 
						 | 
					84bac8356a | ||
| 
						 | 
					2819166539 | ||
| 
						 | 
					8fa18ca7c7 | ||
| 
						 | 
					63290a265c | ||
| 
						 | 
					b854e17995 | ||
| 
						 | 
					5dec9d88f6 | ||
| 
						 | 
					3d0a85ee78 | ||
| 
						 | 
					ac3cdf487f | ||
| 
						 | 
					a47e92f2bc | ||
| 
						 | 
					fc15ddfa91 | ||
| 
						 | 
					d546ef941f | ||
| 
						 | 
					b4bbe3d7b5 | ||
| 
						 | 
					5561d4eaeb | ||
| 
						 | 
					0f6dab394a | ||
| 
						 | 
					adc8c1aa38 | ||
| 
						 | 
					3a82f500d4 | ||
| 
						 | 
					7d1d4831a8 | ||
| 
						 | 
					43539f2dbf | ||
| 
						 | 
					df6830110d | ||
| 
						 | 
					1a98e882dc | ||
| 
						 | 
					c943d84036 | ||
| 
						 | 
					d07a6704d5 | ||
| 
						 | 
					8cfcd5904c | ||
| 
						 | 
					fb8846bb45 | ||
| 
						 | 
					0d0733dd94 | ||
| 
						 | 
					1a524a5a50 | ||
| 
						 | 
					1a2288cccf | ||
| 
						 | 
					8df27d4c3f | ||
| 
						 | 
					0688deca6b | ||
| 
						 | 
					01a4443b6c | ||
| 
						 | 
					e008b054cb | ||
| 
						 | 
					a67d58948d | ||
| 
						 | 
					84c051d097 | ||
| 
						 | 
					b918abfd54 | ||
| 
						 | 
					7f41b7cd93 | ||
| 
						 | 
					4759b4fe2e | ||
| 
						 | 
					e2c8e69d12 | ||
| 
						 | 
					1cf213dad8 | ||
| 
						 | 
					aeb81e547b | ||
| 
						 | 
					479f7703a2 | ||
| 
						 | 
					c7dc396b6d | ||
| 
						 | 
					917e8e155c | ||
| 
						 | 
					80e3030811 | ||
| 
						 | 
					a97e3d827d | ||
| 
						 | 
					029014d9d6 | ||
| 
						 | 
					e4c2922536 | ||
| 
						 | 
					7133ae6aaa | ||
| 
						 | 
					2f7f0ff3a1 | ||
| 
						 | 
					df853bf61e | ||
| 
						 | 
					f0ac753f9b | ||
| 
						 | 
					4d56a975e6 | ||
| 
						 | 
					d56c53c848 | ||
| 
						 | 
					f83b16320d | ||
| 
						 | 
					ac10e27f08 | ||
| 
						 | 
					34df7a6072 | ||
| 
						 | 
					e2cddf1005 | ||
| 
						 | 
					ced423748e | ||
| 
						 | 
					77fb02729e | ||
| 
						 | 
					fef39b9fbe | ||
| 
						 | 
					02810105fb | ||
| 
						 | 
					baad92515b | ||
| 
						 | 
					ab86ddcf02 | ||
| 
						 | 
					bf8eddb13b | ||
| 
						 | 
					e5eaf7a3fe | ||
| 
						 | 
					50f32a3aa5 | ||
| 
						 | 
					eb878710c1 | ||
| 
						 | 
					311980e0e4 | ||
| 
						 | 
					df73170e5a | ||
| 
						 | 
					a12c6b5f35 | ||
| 
						 | 
					522646c64d | ||
| 
						 | 
					4791093e48 | ||
| 
						 | 
					599a455150 | ||
| 
						 | 
					2deef16ebe | ||
| 
						 | 
					989b7be99b | ||
| 
						 | 
					cd473e1395 | ||
| 
						 | 
					e246ebfb2e | ||
| 
						 | 
					8546ae56da | ||
| 
						 | 
					9e227b0192 | ||
| 
						 | 
					ba7737e9f8 | ||
| 
						 | 
					98aa3d51ed | ||
| 
						 | 
					e7cfb5492e | ||
| 
						 | 
					9ed136dc3a | ||
| 
						 | 
					9217216723 | ||
| 
						 | 
					936c408a58 | ||
| 
						 | 
					54427eac9a | ||
| 
						 | 
					e809488cc0 | ||
| 
						 | 
					ed26c57d99 | ||
| 
						 | 
					2a49811f6e | ||
| 
						 | 
					c95acd2568 | ||
| 
						 | 
					6a4e0cf667 | ||
| 
						 | 
					04f4dd8a22 | ||
| 
						 | 
					f33d829ce9 | ||
| 
						 | 
					578671ea94 | ||
| 
						 | 
					d10300c330 | ||
| 
						 | 
					e0555e140f | ||
| 
						 | 
					093989406f | ||
| 
						 | 
					cdb16f08f6 | ||
| 
						 | 
					53139c293b | ||
| 
						 | 
					6a8bdcc315 | ||
| 
						 | 
					fe535939a3 | ||
| 
						 | 
					09e6c11d73 | ||
| 
						 | 
					8112bdfaa8 | ||
| 
						 | 
					f7db9aaa9f | ||
| 
						 | 
					435f972357 | ||
| 
						 | 
					f82b46c16b | ||
| 
						 | 
					bca96f91b2 | ||
| 
						 | 
					6f83a49c63 | ||
| 
						 | 
					72cce391ab | ||
| 
						 | 
					ccc13cc9e1 | ||
| 
						 | 
					020b2c05c8 | ||
| 
						 | 
					4c37c17df1 | ||
| 
						 | 
					8f67acadd8 | ||
| 
						 | 
					ca13c4c1a6 | ||
| 
						 | 
					d0c646c721 | ||
| 
						 | 
					8a055675af | ||
| 
						 | 
					28d2949ebe | ||
| 
						 | 
					c4a0015997 | ||
| 
						 | 
					f564be6aea | ||
| 
						 | 
					988f15e6af | ||
| 
						 | 
					37b6d442bd | ||
| 
						 | 
					fb2467f6f0 | ||
| 
						 | 
					29045b0435 | ||
| 
						 | 
					311a48c64e | ||
| 
						 | 
					01b3815f27 | ||
| 
						 | 
					b0d1c801bd | ||
| 
						 | 
					5aaac06f5b | ||
| 
						 | 
					34adbf0588 | ||
| 
						 | 
					0a4213182e | ||
| 
						 | 
					b0c0258e70 | ||
| 
						 | 
					8110e591d0 | ||
| 
						 | 
					fe05d7aec1 | ||
| 
						 | 
					57f5884070 | ||
| 
						 | 
					f329c74a15 | ||
| 
						 | 
					7c86f3fa9e | ||
| 
						 | 
					203b8b01bf | ||
| 
						 | 
					8a1034a92f | ||
| 
						 | 
					aa0c2dedd9 | ||
| 
						 | 
					d045908e05 | ||
| 
						 | 
					f002a23d2d | ||
| 
						 | 
					29d6d0a906 | ||
| 
						 | 
					c8b58b5c23 | ||
| 
						 | 
					01bfafc5f1 | ||
| 
						 | 
					8c9948bb56 | ||
| 
						 | 
					2d1abaa68e | ||
| 
						 | 
					664a3df0b4 | ||
| 
						 | 
					9ff893881c | ||
| 
						 | 
					94f6c6861a | ||
| 
						 | 
					b1d614e6c4 | ||
| 
						 | 
					7fceb070e5 | ||
| 
						 | 
					06440d0202 | ||
| 
						 | 
					0ecf9f4f2f | ||
| 
						 | 
					5c7c0834c0 | ||
| 
						 | 
					f3a25de11d | ||
| 
						 | 
					041bef8bcd | ||
| 
						 | 
					8998c5f6dd | ||
| 
						 | 
					6e83790308 | ||
| 
						 | 
					d2d4eb4eae | ||
| 
						 | 
					5942a3898c | ||
| 
						 | 
					93421f0fa7 | ||
| 
						 | 
					3a9ab50dd2 | ||
| 
						 | 
					5abd91d6d5 | ||
| 
						 | 
					c3da42516b | ||
| 
						 | 
					6cb5cd48c2 | ||
| 
						 | 
					ec1fae6883 | ||
| 
						 | 
					746fd1122f | ||
| 
						 | 
					9663760ec5 | ||
| 
						 | 
					a3d73d1e23 | ||
| 
						 | 
					d63e14a4b6 | ||
| 
						 | 
					03944e6cd8 | ||
| 
						 | 
					0d1028be2e | ||
| 
						 | 
					6a85259e4d | ||
| 
						 | 
					ebca936b7e | ||
| 
						 | 
					31c4551890 | ||
| 
						 | 
					dd470d4197 | ||
| 
						 | 
					612822490b | ||
| 
						 | 
					f8969605e8 | ||
| 
						 | 
					dd24ffa24e | ||
| 
						 | 
					d0dda48932 | ||
| 
						 | 
					6349b5f654 | ||
| 
						 | 
					a6ff02a3cf | ||
| 
						 | 
					4f57bf786b | ||
| 
						 | 
					6221f6d47d | ||
| 
						 | 
					a922efeafa | ||
| 
						 | 
					5aa42e5e66 | ||
| 
						 | 
					708672ec7e | ||
| 
						 | 
					d2cefbf224 | ||
| 
						 | 
					adb7aa6950 | ||
| 
						 | 
					77f322166e | ||
| 
						 | 
					f3f6e54818 | ||
| 
						 | 
					fb0fec1f25 | ||
| 
						 | 
					b66af9fb4d | ||
| 
						 | 
					6617d576a7 | ||
| 
						 | 
					cd35ead890 | ||
| 
						 | 
					9dc804ee27 | ||
| 
						 | 
					a8ceeaa7b0 | ||
| 
						 | 
					7092f7663e | ||
| 
						 | 
					d9d2edeb08 | ||
| 
						 | 
					dda1ddcb26 | ||
| 
						 | 
					f0c890f160 | ||
| 
						 | 
					4f52d43347 | ||
| 
						 | 
					0ed7db979b | ||
| 
						 | 
					9c78049359 | ||
| 
						 | 
					7882105661 | ||
| 
						 | 
					c000e1d6dd | ||
| 
						 | 
					420dacb22d | ||
| 
						 | 
					ae2f6ad4d1 | ||
| 
						 | 
					2c28d79bf8 | ||
| 
						 | 
					c5069edc78 | ||
| 
						 | 
					282d9e138c | ||
| 
						 | 
					72fcf2cbe1 | ||
| 
						 | 
					6f49f5465b | ||
| 
						 | 
					17b8bd8316 | ||
| 
						 | 
					9b6b9c1fa2 | ||
| 
						 | 
					609a2ca592 | ||
| 
						 | 
					6dabf24bf3 | ||
| 
						 | 
					7e88938932 | ||
| 
						 | 
					c707e64685 | ||
| 
						 | 
					a639690716 | ||
| 
						 | 
					01222dbab7 | ||
| 
						 | 
					93e2506279 | ||
| 
						 | 
					f62d5d3b9d | ||
| 
						 | 
					0665acd190 | ||
| 
						 | 
					fea05e9d33 | ||
| 
						 | 
					7a03c7d56f | ||
| 
						 | 
					2dc2aec954 | ||
| 
						 | 
					39c6c2417a | ||
| 
						 | 
					ff72d6a146 | ||
| 
						 | 
					603d0d0c7c | ||
| 
						 | 
					28883f711b | ||
| 
						 | 
					e914828add | ||
| 
						 | 
					c1480029fb | ||
| 
						 | 
					40f622949e | ||
| 
						 | 
					63096ac2bc | ||
| 
						 | 
					03d5a0ec1d | ||
| 
						 | 
					1c873e0034 | ||
| 
						 | 
					bcb47c306c | ||
| 
						 | 
					01c4d3c225 | ||
| 
						 | 
					c2aaae4818 | ||
| 
						 | 
					3f678e218d | ||
| 
						 | 
					c2a59cb476 | ||
| 
						 | 
					f8a1bd4e79 | ||
| 
						 | 
					d6e039a1d1 | ||
| 
						 | 
					0f1a7c2b69 | ||
| 
						 | 
					40ad9f4911 | ||
| 
						 | 
					4116caff6a | ||
| 
						 | 
					0b69f72315 | ||
| 
						 | 
					c569f5ddcf | ||
| 
						 | 
					62f9e181e0 | ||
| 
						 | 
					235a97ea10 | ||
| 
						 | 
					e541ae400c | ||
| 
						 | 
					4822abde86 | ||
| 
						 | 
					b7e52812f8 | ||
| 
						 | 
					69118120d9 | ||
| 
						 | 
					7cba0c6fb0 | ||
| 
						 | 
					5fac67ce15 | ||
| 
						 | 
					98c733108e | ||
| 
						 | 
					782186e13d | ||
| 
						 | 
					4e1f6518e8 | ||
| 
						 | 
					53e0fe8e51 | ||
| 
						 | 
					0e547390da | ||
| 
						 | 
					86b52df839 | ||
| 
						 | 
					d685fdf54a | ||
| 
						 | 
					d9caab4108 | ||
| 
						 | 
					44b68f140e | ||
| 
						 | 
					3a3d97dfa7 | ||
| 
						 | 
					47898b527c | ||
| 
						 | 
					a35f36ad39 | ||
| 
						 | 
					d13a397f8e | ||
| 
						 | 
					df999723f8 | ||
| 
						 | 
					8236e840a7 | ||
| 
						 | 
					e5b3625f73 | ||
| 
						 | 
					2e4645310b | ||
| 
						 | 
					50a32b387e | ||
| 
						 | 
					2059283707 | ||
| 
						 | 
					8e3af515c9 | ||
| 
						 | 
					6f88f0ea3f | ||
| 
						 | 
					d2f37cf3f9 | ||
| 
						 | 
					7c30d6254e | ||
| 
						 | 
					64fb39a653 | ||
| 
						 | 
					91895aa70c | ||
| 
						 | 
					68dfaf238b | ||
| 
						 | 
					ebf13a0ba0 | ||
| 
						 | 
					2bff9937b7 | ||
| 
						 | 
					256395c28d | ||
| 
						 | 
					3346bc8bba | ||
| 
						 | 
					6fe22a7e62 | ||
| 
						 | 
					757b98748b | ||
| 
						 | 
					7a778f3f33 | ||
| 
						 | 
					993044c870 | ||
| 
						 | 
					a8c1b63edb | ||
| 
						 | 
					db7d946e1b | ||
| 
						 | 
					41d9059a2f | ||
| 
						 | 
					e26e0d7c01 | ||
| 
						 | 
					ad41c07a1f | ||
| 
						 | 
					9576d246ee | ||
| 
						 | 
					988d3ea8ba | ||
| 
						 | 
					0767b92b62 | ||
| 
						 | 
					5732f3b044 | ||
| 
						 | 
					712115b6ce | ||
| 
						 | 
					9283559c6b | ||
| 
						 | 
					6b393438e9 | ||
| 
						 | 
					2064abe16d | ||
| 
						 | 
					b605982f94 | ||
| 
						 | 
					343b9ab455 | ||
| 
						 | 
					dcb226b202 | ||
| 
						 | 
					2243021b58 | ||
| 
						 | 
					d5134e88b1 | ||
| 
						 | 
					c59adf612f | ||
| 
						 | 
					93b628d9a8 | ||
| 
						 | 
					6bac551d9f | ||
| 
						 | 
					70a35656e4 | ||
| 
						 | 
					047c18eac0 | ||
| 
						 | 
					b4a86ce6cf | ||
| 
						 | 
					a82d8ea0c3 | ||
| 
						 | 
					b778eed419 | ||
| 
						 | 
					ad57faa9a9 | ||
| 
						 | 
					a9b5e8d036 | ||
| 
						 | 
					8be704e591 | ||
| 
						 | 
					b622a8fa58 | ||
| 
						 | 
					a519e5c475 | ||
| 
						 | 
					d620b6dd5e | ||
| 
						 | 
					99335d986e | ||
| 
						 | 
					7895cd92cd | ||
| 
						 | 
					8b2c032da6 | ||
| 
						 | 
					da336247eb | ||
| 
						 | 
					dabd27d4be | ||
| 
						 | 
					fdda47db6e | ||
| 
						 | 
					efa6fd03e5 | ||
| 
						 | 
					9e3e34acf5 | ||
| 
						 | 
					a2d0c1bf18 | ||
| 
						 | 
					7663716ae8 | ||
| 
						 | 
					c2cacb3478 | ||
| 
						 | 
					84666b54b9 | ||
| 
						 | 
					2b91c23bf3 | ||
| 
						 | 
					3297267a16 | ||
| 
						 | 
					a9e653724c | ||
| 
						 | 
					5e79a1f500 | ||
| 
						 | 
					d4ff98680a | ||
| 
						 | 
					ba8d255cb4 | ||
| 
						 | 
					06f4ad922c | ||
| 
						 | 
					bff06e448b | ||
| 
						 | 
					d48ffa2913 | ||
| 
						 | 
					d97c3a7e01 | ||
| 
						 | 
					0b1161f7ef | ||
| 
						 | 
					061e1a471d | ||
| 
						 | 
					a39d874600 | ||
| 
						 | 
					de96376565 | ||
| 
						 | 
					c54c20ab3c | ||
| 
						 | 
					70fafa473b | ||
| 
						 | 
					2e436eae6b | ||
| 
						 | 
					fd7e861ff5 | ||
| 
						 | 
					792108686c | ||
| 
						 | 
					fa1b5117fd | ||
| 
						 | 
					b0bd9e0a34 | ||
| 
						 | 
					05dc97099a | ||
| 
						 | 
					9de61fcf58 | ||
| 
						 | 
					fc7348d46d | ||
| 
						 | 
					8be2456c7e | ||
| 
						 | 
					bb5f7249a6 | ||
| 
						 | 
					7f7175b184 | ||
| 
						 | 
					cf5c640ae4 | ||
| 
						 | 
					6b9371d105 | ||
| 
						 | 
					9a82057303 | ||
| 
						 | 
					48584e94c4 | ||
| 
						 | 
					fc94a5d0ee | ||
| 
						 | 
					d8024a5928 | ||
| 
						 | 
					2034ab4f6c | ||
| 
						 | 
					24029cc918 | ||
| 
						 | 
					9a9d5964ee | ||
| 
						 | 
					4e4a512107 | ||
| 
						 | 
					0729ed538e | ||
| 
						 | 
					24b75b7ed6 | ||
| 
						 | 
					58b70b42dd | ||
| 
						 | 
					1496bc1b07 | ||
| 
						 | 
					bfbf88b2ea | ||
| 
						 | 
					e621b938e3 | ||
| 
						 | 
					ec3618ecb8 | ||
| 
						 | 
					792a24f38d | ||
| 
						 | 
					652e8a015b | ||
| 
						 | 
					59e6e798dd | ||
| 
						 | 
					e5c2dbc7ec | ||
| 
						 | 
					756f71c382 | ||
| 
						 | 
					b7535693fa | ||
| 
						 | 
					06a3505698 | ||
| 
						 | 
					0372d17a11 | ||
| 
						 | 
					4525588116 | ||
| 
						 | 
					68e957c147 | ||
| 
						 | 
					99f5ed1461 | ||
| 
						 | 
					59f67796dc | ||
| 
						 | 
					aafdfa933e | ||
| 
						 | 
					3208c8ed1e | ||
| 
						 | 
					6bf733e24e | ||
| 
						 | 
					65d3e8fbfc | ||
| 
						 | 
					a29d65d47c | ||
| 
						 | 
					efa8f0730d | ||
| 
						 | 
					0af1edefff | ||
| 
						 | 
					023d26f521 | ||
| 
						 | 
					5068619f1b | ||
| 
						 | 
					5b2457af0b | ||
| 
						 | 
					900b4f1af9 | ||
| 
						 | 
					4c22a98b0b | ||
| 
						 | 
					3b8ca80900 | ||
| 
						 | 
					1ef6fd8fb0 | ||
| 
						 | 
					942b0de7fd | ||
| 
						 | 
					859cca49d1 | ||
| 
						 | 
					dc6eff83ea | ||
| 
						 | 
					38ff66debd | ||
| 
						 | 
					1d2e0f74ea | ||
| 
						 | 
					8f7ff25624 | ||
| 
						 | 
					97aca8e54c | ||
| 
						 | 
					95acf19067 | ||
| 
						 | 
					3d0899aa58 | ||
| 
						 | 
					bf60e40d0b | ||
| 
						 | 
					c9094ca537 | ||
| 
						 | 
					68b3fd6b8f | ||
| 
						 | 
					9323b3a248 | ||
| 
						 | 
					b55e9329d9 | ||
| 
						 | 
					a5b4105971 | ||
| 
						 | 
					d1feaa935d | ||
| 
						 | 
					6919930aaa | ||
| 
						 | 
					69633826bb | ||
| 
						 | 
					771162bfb1 | ||
| 
						 | 
					ba785e29e9 | ||
| 
						 | 
					138d6e505b | ||
| 
						 | 
					2748e6ba29 | ||
| 
						 | 
					dbd4e927d8 | ||
| 
						 | 
					e73d47918f | ||
| 
						 | 
					b881bc071e | ||
| 
						 | 
					1d0395d1c7 | ||
| 
						 | 
					616c787e37 | ||
| 
						 | 
					0c4de2bc97 | ||
| 
						 | 
					2c7b104f4a | ||
| 
						 | 
					78951c197a | ||
| 
						 | 
					07c1cf7137 | ||
| 
						 | 
					d26141151a | ||
| 
						 | 
					f59dbe4a88 | ||
| 
						 | 
					8dae7f8225 | ||
| 
						 | 
					5811389891 | ||
| 
						 | 
					debcaf6fb7 | ||
| 
						 | 
					b8d10a62c2 | ||
| 
						 | 
					d2b209234f | ||
| 
						 | 
					34c9d8be50 | ||
| 
						 | 
					ae57ad0c81 | ||
| 
						 | 
					0c1520dd9c | ||
| 
						 | 
					d594f43ebd | ||
| 
						 | 
					125c693e3f | ||
| 
						 | 
					ad2f857e15 | ||
| 
						 | 
					e445d6aada | ||
| 
						 | 
					88fbb0ffbb | ||
| 
						 | 
					231908fe9f | ||
| 
						 | 
					f137cc10f4 | ||
| 
						 | 
					c2f5ac9eba | ||
| 
						 | 
					5764c988af | ||
| 
						 | 
					ccc2fbfd67 | ||
| 
						 | 
					1a8f8adc2a | ||
| 
						 | 
					7a242bb4ed | ||
| 
						 | 
					10b4adb8e6 | ||
| 
						 | 
					3b8bb09ae3 | ||
| 
						 | 
					83b7181bcb | ||
| 
						 | 
					8886b7e141 | ||
| 
						 | 
					7dcc4d030b | ||
| 
						 | 
					b9398897c1 | ||
| 
						 | 
					140db85d21 | ||
| 
						 | 
					ccce4b19e8 | ||
| 
						 | 
					8cb9be7560 | ||
| 
						 | 
					953f0569fb | ||
| 
						 | 
					34c229fd33 | ||
| 
						 | 
					958ad0d750 | ||
| 
						 | 
					36ddd9dd69 | ||
| 
						 | 
					38259c96c9 | ||
| 
						 | 
					c054fb8a2c | ||
| 
						 | 
					5a0b8328d8 | ||
| 
						 | 
					ffa19426d7 | ||
| 
						 | 
					c123804294 | ||
| 
						 | 
					4e24551b90 | ||
| 
						 | 
					657b1c60ae | ||
| 
						 | 
					dc54b17778 | ||
| 
						 | 
					1fb214165b | ||
| 
						 | 
					51cb5da7f0 | ||
| 
						 | 
					81b2fd78f5 | ||
| 
						 | 
					69002fb1e6 | ||
| 
						 | 
					75332a752d | ||
| 
						 | 
					b528f48417 | ||
| 
						 | 
					ec7a79049a | ||
| 
						 | 
					6ddad6b299 | ||
| 
						 | 
					16dc7762f9 | ||
| 
						 | 
					41f84447cc | ||
| 
						 | 
					ce073a704b | ||
| 
						 | 
					113232ebb6 | ||
| 
						 | 
					dc0ed8857f | ||
| 
						 | 
					bb6b77bd98 | ||
| 
						 | 
					dcc80f9032 | ||
| 
						 | 
					dd554bcdf4 | ||
| 
						 | 
					f376a39e55 | ||
| 
						 | 
					8dcc9d6b66 | ||
| 
						 | 
					a13a1225b7 | ||
| 
						 | 
					0ec84be5da | ||
| 
						 | 
					b1cefb7e3e | ||
| 
						 | 
					cc0c1c08b9 | ||
| 
						 | 
					3a67884451 | ||
| 
						 | 
					72e716cdf1 | ||
| 
						 | 
					40e06c9819 | ||
| 
						 | 
					ad6c5ff11d | ||
| 
						 | 
					335512e232 | ||
| 
						 | 
					2622e59b0b | ||
| 
						 | 
					35e6a13cd1 | ||
| 
						 | 
					a576c9f21f | ||
| 
						 | 
					b48490badc | ||
| 
						 | 
					71a438e2cb | ||
| 
						 | 
					272d6f2a8b | ||
| 
						 | 
					5c22065135 | ||
| 
						 | 
					e7dd6c52ac | ||
| 
						 | 
					3bf042dce9 | ||
| 
						 | 
					09ed1aed93 | ||
| 
						 | 
					53d3718028 | ||
| 
						 | 
					2b5dce5232 | ||
| 
						 | 
					9ad84150aa | ||
| 
						 | 
					64f798d4b2 | ||
| 
						 | 
					f43e04e15a | ||
| 
						 | 
					88d72f8c9a | ||
| 
						 | 
					9826726a72 | ||
| 
						 | 
					c66d0550e8 | ||
| 
						 | 
					4aeacfd16e | ||
| 
						 | 
					58fa63ad88 | ||
| 
						 | 
					94f944dc9c | ||
| 
						 | 
					116ddbdd01 | ||
| 
						 | 
					1c0697b5d4 | ||
| 
						 | 
					434ca47ea0 | ||
| 
						 | 
					397ef72b16 | ||
| 
						 | 
					7ca9245735 | ||
| 
						 | 
					69856286e8 | ||
| 
						 | 
					ad43d6a5bc | ||
| 
						 | 
					1e5004f495 | ||
| 
						 | 
					253161d3d0 | ||
| 
						 | 
					ab47e201c7 | ||
| 
						 | 
					42984fa72a | ||
| 
						 | 
					e7864a28a1 | ||
| 
						 | 
					21803607e7 | ||
| 
						 | 
					c0523590b4 | ||
| 
						 | 
					c7f091ab10 | ||
| 
						 | 
					7479e0aada | ||
| 
						 | 
					62b366a5ec | ||
| 
						 | 
					2b39988707 | ||
| 
						 | 
					f9e7291050 | ||
| 
						 | 
					4de642ff28 | ||
| 
						 | 
					0384efcfc2 | ||
| 
						 | 
					bf91443f38 | ||
| 
						 | 
					4a5970b4af | ||
| 
						 | 
					e3fd68c849 | ||
| 
						 | 
					df0de2fc2d | ||
| 
						 | 
					0c3568fad5 | ||
| 
						 | 
					976f5d91ed | ||
| 
						 | 
					0f3d4d9a47 | ||
| 
						 | 
					ad1f4429c9 | ||
| 
						 | 
					7590d5eacb | ||
| 
						 | 
					c5974b8833 | ||
| 
						 | 
					511c8de6f3 | ||
| 
						 | 
					a718ac7ee0 | ||
| 
						 | 
					ef832becf1 | ||
| 
						 | 
					3a62455948 | ||
| 
						 | 
					297824e2d7 | ||
| 
						 | 
					d92f297bc0 | ||
| 
						 | 
					7a0827e3d0 | ||
| 
						 | 
					ef256a64b8 | ||
| 
						 | 
					1de941e837 | ||
| 
						 | 
					28b65cb810 | ||
| 
						 | 
					6ff3942e8b | ||
| 
						 | 
					ef5d959788 | ||
| 
						 | 
					5bbee1a1fe | ||
| 
						 | 
					6a2c58fcc0 | ||
| 
						 | 
					bdb9546ca3 | ||
| 
						 | 
					46af4cad6e | ||
| 
						 | 
					76a238912b | ||
| 
						 | 
					4e6bdb31ac | ||
| 
						 | 
					80d03a631e | ||
| 
						 | 
					6b27f2d2cf | ||
| 
						 | 
					7cb6729fa7 | ||
| 
						 | 
					2f46267994 | ||
| 
						 | 
					cdda648360 | ||
| 
						 | 
					f2d677d51a | ||
| 
						 | 
					c2ee0f0864 | ||
| 
						 | 
					2a84db7f85 | ||
| 
						 | 
					8187a4bce9 | ||
| 
						 | 
					97681d142e | ||
| 
						 | 
					b2430097f2 | ||
| 
						 | 
					7da12a878f | ||
| 
						 | 
					a31700e16f | ||
| 
						 | 
					7854522792 | ||
| 
						 | 
					a6a9ebfde2 | ||
| 
						 | 
					c6cbe2748e | ||
| 
						 | 
					f9a7f00843 | ||
| 
						 | 
					f0b183a552 | ||
| 
						 | 
					338ada5c9f | ||
| 
						 | 
					ef88f9923f | ||
| 
						 | 
					6f8c7d9ec4 | ||
| 
						 | 
					ec769ccf72 | ||
| 
						 | 
					045952939e | ||
| 
						 | 
					1c51cac5ba | ||
| 
						 | 
					ea11462e1e | ||
| 
						 | 
					62f9736b1d | ||
| 
						 | 
					1f8a1f0046 | ||
| 
						 | 
					172507acb5 | ||
| 
						 | 
					434ab65c16 | ||
| 
						 | 
					909a526967 | ||
| 
						 | 
					cd6f4fb93f | ||
| 
						 | 
					c19458696e | ||
| 
						 | 
					cb5f793ede | ||
| 
						 | 
					318b930e9f | ||
| 
						 | 
					9296a078a7 | ||
| 
						 | 
					5dc776e55f | ||
| 
						 | 
					72d60f30f7 | ||
| 
						 | 
					869743a742 | ||
| 
						 | 
					7b03e07908 | ||
| 
						 | 
					348f880e15 | ||
| 
						 | 
					737188ae50 | ||
| 
						 | 
					db21731b14 | ||
| 
						 | 
					cdb4fa2487 | ||
| 
						 | 
					514204f0d4 | ||
| 
						 | 
					ead597d0fb | ||
| 
						 | 
					afbf989715 | ||
| 
						 | 
					01b62a16c3 | ||
| 
						 | 
					c5eba04517 | ||
| 
						 | 
					282313ab52 | ||
| 
						 | 
					d274545e77 | ||
| 
						 | 
					45ac577c4d | ||
| 
						 | 
					09402fdb22 | ||
| 
						 | 
					89e7448007 | ||
| 
						 | 
					1ea6f957bc | ||
| 
						 | 
					f44fca0a4b | ||
| 
						 | 
					52d2f62a57 | ||
| 
						 | 
					d3fda37615 | ||
| 
						 | 
					cbe3092404 | ||
| 
						 | 
					6dfe3039d0 | ||
| 
						 | 
					d6009453df | ||
| 
						 | 
					2a8668ea60 | ||
| 
						 | 
					cc0d433621 | ||
| 
						 | 
					c81323ef91 | ||
| 
						 | 
					1fe89fb364 | ||
| 
						 | 
					961c27f1c2 | ||
| 
						 | 
					fe4a14e6cc | ||
| 
						 | 
					ee58ad1ac0 | ||
| 
						 | 
					c0ff899812 | ||
| 
						 | 
					d9c938de33 | ||
| 
						 | 
					56547b3d50 | ||
| 
						 | 
					5026bc7a78 | ||
| 
						 | 
					27364ee72c | ||
| 
						 | 
					ece71a0228 | ||
| 
						 | 
					073828235f | ||
| 
						 | 
					41bcc8c0f4 | ||
| 
						 | 
					a0ea2aae6e | ||
| 
						 | 
					f34b46a621 | ||
| 
						 | 
					7217a4f7a4 | ||
| 
						 | 
					6383eca54a | ||
| 
						 | 
					e55bd1e559 | ||
| 
						 | 
					9e8b701dea | ||
| 
						 | 
					a4431abea8 | ||
| 
						 | 
					5844c1767b | ||
| 
						 | 
					9a70bfa471 | ||
| 
						 | 
					b406c6403c | ||
| 
						 | 
					499625f266 | ||
| 
						 | 
					6b773553fc | ||
| 
						 | 
					15fe049a99 | ||
| 
						 | 
					e4555f6997 | ||
| 
						 | 
					470071e0b0 | ||
| 
						 | 
					ea1be8e7bf | ||
| 
						 | 
					84a830195f | ||
| 
						 | 
					e62c3e00c1 | ||
| 
						 | 
					07e790f900 | ||
| 
						 | 
					640142fc0c | ||
| 
						 | 
					5c339d4597 | ||
| 
						 | 
					a4931f5d78 | ||
| 
						 | 
					5e1e543b06 | ||
| 
						 | 
					df929f9445 | ||
| 
						 | 
					d8e719d1c4 | ||
| 
						 | 
					3067e482fc | ||
| 
						 | 
					ed5930e934 | ||
| 
						 | 
					ffea3597f4 | ||
| 
						 | 
					193d3e0206 | ||
| 
						 | 
					c8f4fbb7dd | ||
| 
						 | 
					c855bc31b4 | ||
| 
						 | 
					b924b179ab | ||
| 
						 | 
					3df0fee3de | ||
| 
						 | 
					b601560e81 | ||
| 
						 | 
					e5775cf812 | ||
| 
						 | 
					26dd1f8532 | ||
| 
						 | 
					5143a5b5c5 | ||
| 
						 | 
					15ce27992e | ||
| 
						 | 
					dbc2812022 | ||
| 
						 | 
					dce3713f12 | ||
| 
						 | 
					f849d45bb6 | ||
| 
						 | 
					8ad06fb9ea | ||
| 
						 | 
					9124d9d6e6 | ||
| 
						 | 
					45ebe51e4f | ||
| 
						 | 
					407661d56b | ||
| 
						 | 
					998d4229af | ||
| 
						 | 
					a02d2e2e11 | ||
| 
						 | 
					72fa68849f | ||
| 
						 | 
					33f17f75a0 | ||
| 
						 | 
					23edb18d7e | ||
| 
						 | 
					07ff3a853f | ||
| 
						 | 
					2cf36bdb46 | ||
| 
						 | 
					50848c2f4d | ||
| 
						 | 
					d32633b3c7 | ||
| 
						 | 
					b37739eec2 | ||
| 
						 | 
					28f87dc804 | ||
| 
						 | 
					41879e41e6 | ||
| 
						 | 
					fc0a6546a2 | ||
| 
						 | 
					ffd4280d6c | ||
| 
						 | 
					f859b346a6 | ||
| 
						 | 
					cb0677cafe | ||
| 
						 | 
					c6956527d1 | ||
| 
						 | 
					72c6bfaa50 | ||
| 
						 | 
					7927b5f624 | ||
| 
						 | 
					b7aad39daf | ||
| 
						 | 
					f48de6dd43 | ||
| 
						 | 
					79d73d8f8b | ||
| 
						 | 
					cc5947467f | ||
| 
						 | 
					e152f128c8 | ||
| 
						 | 
					99bd808ebe | ||
| 
						 | 
					beb5f3dc9d | ||
| 
						 | 
					f5c3b3446f | ||
| 
						 | 
					db3b955b0f | ||
| 
						 | 
					f431c7402f | ||
| 
						 | 
					5516f65971 | ||
| 
						 | 
					9471df0a1b | ||
| 
						 | 
					6d39f64be7 | ||
| 
						 | 
					4907e6f6d7 | ||
| 
						 | 
					1ccee86705 | ||
| 
						 | 
					542fb2175b | ||
| 
						 | 
					6ec9cfb044 | ||
| 
						 | 
					66e0ff8392 | ||
| 
						 | 
					1fb0a7109d | ||
| 
						 | 
					b89d0a9a73 | ||
| 
						 | 
					4bb779d9a5 | ||
| 
						 | 
					386a5b6362 | ||
| 
						 | 
					e32a999cd0 | ||
| 
						 | 
					192eb49589 | ||
| 
						 | 
					5d70ff702b | ||
| 
						 | 
					a7b05db2a1 | ||
| 
						 | 
					45e346cf1b | ||
| 
						 | 
					80e2bfada3 | ||
| 
						 | 
					16e7bd0388 | ||
| 
						 | 
					b3fb35783e | ||
| 
						 | 
					a79c6aa9e0 | ||
| 
						 | 
					4bb58b2de9 | ||
| 
						 | 
					4e10881331 | ||
| 
						 | 
					cec4a81e14 | ||
| 
						 | 
					da45923d05 | ||
| 
						 | 
					31a61b598b | ||
| 
						 | 
					9c0506592b | ||
| 
						 | 
					beeb0c7c5a | ||
| 
						 | 
					b2f05faee0 | ||
| 
						 | 
					bfbc6a4bad | ||
| 
						 | 
					8c9e0e552d | ||
| 
						 | 
					8aaf9fd83f | ||
| 
						 | 
					08057720b8 | ||
| 
						 | 
					bfaa648837 | ||
| 
						 | 
					d504daef91 | ||
| 
						 | 
					8375e1d64d | ||
| 
						 | 
					cf5193d3e5 | ||
| 
						 | 
					b8d3ef2f49 | ||
| 
						 | 
					3bf6320030 | ||
| 
						 | 
					708b928c73 | ||
| 
						 | 
					649366ff44 | ||
| 
						 | 
					e5c9e87fad | ||
| 
						 | 
					c490388e80 | ||
| 
						 | 
					24ec5a6e9d | ||
| 
						 | 
					f3d9d707b6 | ||
| 
						 | 
					090e10730c | ||
| 
						 | 
					fbc84861c7 | ||
| 
						 | 
					e763469af8 | ||
| 
						 | 
					6df1d5222d | ||
| 
						 | 
					58fb7a02f6 | ||
| 
						 | 
					3d51ac8df0 | ||
| 
						 | 
					6fe4ff7f85 | ||
| 
						 | 
					3c0c514e44 | ||
| 
						 | 
					2253d4bc16 | ||
| 
						 | 
					e5cc19de43 | ||
| 
						 | 
					ed5e2dd332 | ||
| 
						 | 
					09b7c6f550 | ||
| 
						 | 
					df315a1f51 | ||
| 
						 | 
					7ee4bb621c | ||
| 
						 | 
					24874f4c3c | ||
| 
						 | 
					c128880033 | ||
| 
						 | 
					a66e94a0b0 | ||
| 
						 | 
					56870ed4a8 | ||
| 
						 | 
					3ac720df47 | ||
| 
						 | 
					1bc757ad06 | ||
| 
						 | 
					f72abc6f3d | ||
| 
						 | 
					5ac88de985 | ||
| 
						 | 
					5404617d43 | ||
| 
						 | 
					12467a18e6 | ||
| 
						 | 
					1db7043a4d | ||
| 
						 | 
					49932747b3 | ||
| 
						 | 
					55db190875 | ||
| 
						 | 
					71fe2f7ed3 | ||
| 
						 | 
					ffc112c9d0 | ||
| 
						 | 
					d3e48e296f | ||
| 
						 | 
					14f6ae75ea | ||
| 
						 | 
					c84efe64d3 | ||
| 
						 | 
					10e89a7dbb | ||
| 
						 | 
					ef44acbf10 | ||
| 
						 | 
					06da540ab0 | ||
| 
						 | 
					0826b367d6 | ||
| 
						 | 
					329bf861d6 | ||
| 
						 | 
					9dcd3d18a0 | ||
| 
						 | 
					40c017fd54 | ||
| 
						 | 
					db66cd88b6 | ||
| 
						 | 
					f0bcf81a98 | ||
| 
						 | 
					86c205fe43 | ||
| 
						 | 
					6a0b343289 | ||
| 
						 | 
					c6414138c7 | ||
| 
						 | 
					36b355eb82 | ||
| 
						 | 
					9ca4e8f32a | ||
| 
						 | 
					1b88b7a166 | ||
| 
						 | 
					caf352ff06 | ||
| 
						 | 
					54106179a1 | ||
| 
						 | 
					607601b3a4 | ||
| 
						 | 
					f58828cb82 | ||
| 
						 | 
					11330af05f | ||
| 
						 | 
					fbe1bca1b9 | ||
| 
						 | 
					24a5325db3 | ||
| 
						 | 
					1ec3140759 | ||
| 
						 | 
					ca8db7696e | ||
| 
						 | 
					c9190574a9 | ||
| 
						 | 
					bfeb0b3639 | ||
| 
						 | 
					cbc1334b8d | ||
| 
						 | 
					08cbb97ec9 | ||
| 
						 | 
					5719cc1a24 | ||
| 
						 | 
					d9513e5ff2 | ||
| 
						 | 
					b5a0e8b2c0 | ||
| 
						 | 
					b32b918936 | ||
| 
						 | 
					0f47ffd908 | ||
| 
						 | 
					cd018ad3a5 | ||
| 
						 | 
					24dfecb6f0 | ||
| 
						 | 
					ab027a6ae2 | ||
| 
						 | 
					556d071e7f | ||
| 
						 | 
					939fb313df | ||
| 
						 | 
					b5639a6472 | ||
| 
						 | 
					f50e40e0b8 | ||
| 
						 | 
					6f07421911 | ||
| 
						 | 
					adf48246a9 | ||
| 
						 | 
					7be9291b13 | ||
| 
						 | 
					ea9e75039b | ||
| 
						 | 
					a5fb036011 | ||
| 
						 | 
					e55506f9db | ||
| 
						 | 
					50ec1d0445 | ||
| 
						 | 
					3d5e1d8d91 | ||
| 
						 | 
					db2128a344 | ||
| 
						 | 
					cae283dc86 | ||
| 
						 | 
					7afcb0fb04 | ||
| 
						 | 
					10f830c3ef | ||
| 
						 | 
					7a5c3aa7ed | ||
| 
						 | 
					2b50406856 | ||
| 
						 | 
					10a2a7e0fc | ||
| 
						 | 
					7a564b222d | ||
| 
						 | 
					21db43db06 | ||
| 
						 | 
					5009b3029f | ||
| 
						 | 
					57a029189c | ||
| 
						 | 
					671d68bc2c | ||
| 
						 | 
					5946c37925 | ||
| 
						 | 
					17a37b1de9 | ||
| 
						 | 
					e7827a6997 | ||
| 
						 | 
					2347e043a9 | ||
| 
						 | 
					00965fe19e | ||
| 
						 | 
					9681dfb458 | ||
| 
						 | 
					5e631bc6ba | ||
| 
						 | 
					b5f660398c | ||
| 
						 | 
					d50bdf619f | ||
| 
						 | 
					4e448b21ff | ||
| 
						 | 
					2a78c2970d | ||
| 
						 | 
					0cb715bb76 | ||
| 
						 | 
					7d03823afd | ||
| 
						 | 
					8e1c9f5042 | ||
| 
						 | 
					980b7cda8f | ||
| 
						 | 
					3a72dd5cb6 | ||
| 
						 | 
					3178243811 | ||
| 
						 | 
					d30e2f2a4f | ||
| 
						 | 
					3637be251e | ||
| 
						 | 
					2aea27d272 | ||
| 
						 | 
					ceb9b1d1ff | ||
| 
						 | 
					ccfa1e23f0 | ||
| 
						 | 
					290da8df2d | ||
| 
						 | 
					4b1d73791d | ||
| 
						 | 
					7e8012c1a0 | ||
| 
						 | 
					15cd602e8b | ||
| 
						 | 
					598f5b241f | ||
| 
						 | 
					335e69e6cd | ||
| 
						 | 
					05fe5db030 | ||
| 
						 | 
					710096b1c6 | ||
| 
						 | 
					07b882c801 | ||
| 
						 | 
					3e5331a263 | ||
| 
						 | 
					897277992b | ||
| 
						 | 
					1424091ee5 | ||
| 
						 | 
					61ec16cdfc | ||
| 
						 | 
					e5cb5756aa | ||
| 
						 | 
					9e1c3e8f01 | ||
| 
						 | 
					448e1690aa | ||
| 
						 | 
					8267f01ccd | ||
| 
						 | 
					6f9439e1bc | ||
| 
						 | 
					06994c0dfc | ||
| 
						 | 
					dee5d639e2 | ||
| 
						 | 
					df6730be55 | ||
| 
						 | 
					6226dae05c | ||
| 
						 | 
					9c6a475a6e | ||
| 
						 | 
					8294d10d5b | ||
| 
						 | 
					67558bec47 | ||
| 
						 | 
					6c1ef398bb | ||
| 
						 | 
					84873d4074 | ||
| 
						 | 
					58a0b28a39 | ||
| 
						 | 
					0469e19f54 | ||
| 
						 | 
					dbcfa7b599 | ||
| 
						 | 
					b37d3a66cc | ||
| 
						 | 
					7e495a5e27 | ||
| 
						 | 
					c41547fd4a | ||
| 
						 | 
					0d47d41c85 | ||
| 
						 | 
					df68403b6d | ||
| 
						 | 
					57bdc2b885 | ||
| 
						 | 
					f565ff5def | ||
| 
						 | 
					8ece639987 | ||
| 
						 | 
					b35f509784 | ||
| 
						 | 
					41a3a17456 | ||
| 
						 | 
					cbbafbcca2 | ||
| 
						 | 
					c75566b374 | ||
| 
						 | 
					f1954df573 | ||
| 
						 | 
					9e4fa5dcf1 | ||
| 
						 | 
					0809673ba9 | ||
| 
						 | 
					b386284180 | ||
| 
						 | 
					515519bc87 | ||
| 
						 | 
					5404163be0 | ||
| 
						 | 
					0b193eee43 | ||
| 
						 | 
					7333123ba4 | ||
| 
						 | 
					d99c5ed890 | ||
| 
						 | 
					04740fbcbb | ||
| 
						 | 
					6a7440f7d3 | ||
| 
						 | 
					14299bb2cc | ||
| 
						 | 
					66cebfc992 | ||
| 
						 | 
					108b8e6705 | ||
| 
						 | 
					4eaa6afa4d | ||
| 
						 | 
					f643a46bbf | ||
| 
						 | 
					aae63a7ff3 | ||
| 
						 | 
					582567696e | ||
| 
						 | 
					2e0c89409d | ||
| 
						 | 
					7bb7456a8b | ||
| 
						 | 
					0372e12b81 | ||
| 
						 | 
					a6873c1520 | ||
| 
						 | 
					f11220da3a | ||
| 
						 | 
					bb9793d5b7 | ||
| 
						 | 
					e99af991ec | ||
| 
						 | 
					abf3708cc2 | ||
| 
						 | 
					4395d6156d | ||
| 
						 | 
					04ba53c870 | 
							
								
								
									
										25
									
								
								.clang-tidy
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								.clang-tidy
									
									
									
									
									
								
							@@ -5,11 +5,8 @@ Checks: >-
 | 
				
			|||||||
  -altera-*,
 | 
					  -altera-*,
 | 
				
			||||||
  -android-*,
 | 
					  -android-*,
 | 
				
			||||||
  -boost-*,
 | 
					  -boost-*,
 | 
				
			||||||
  -bugprone-branch-clone,
 | 
					 | 
				
			||||||
  -bugprone-easily-swappable-parameters,
 | 
					 | 
				
			||||||
  -bugprone-narrowing-conversions,
 | 
					  -bugprone-narrowing-conversions,
 | 
				
			||||||
  -bugprone-signed-char-misuse,
 | 
					  -bugprone-signed-char-misuse,
 | 
				
			||||||
  -bugprone-too-small-loop-variable,
 | 
					 | 
				
			||||||
  -cert-dcl50-cpp,
 | 
					  -cert-dcl50-cpp,
 | 
				
			||||||
  -cert-err58-cpp,
 | 
					  -cert-err58-cpp,
 | 
				
			||||||
  -cert-oop57-cpp,
 | 
					  -cert-oop57-cpp,
 | 
				
			||||||
@@ -19,12 +16,10 @@ Checks: >-
 | 
				
			|||||||
  -clang-diagnostic-delete-abstract-non-virtual-dtor,
 | 
					  -clang-diagnostic-delete-abstract-non-virtual-dtor,
 | 
				
			||||||
  -clang-diagnostic-delete-non-abstract-non-virtual-dtor,
 | 
					  -clang-diagnostic-delete-non-abstract-non-virtual-dtor,
 | 
				
			||||||
  -clang-diagnostic-shadow-field,
 | 
					  -clang-diagnostic-shadow-field,
 | 
				
			||||||
  -clang-diagnostic-sign-compare,
 | 
					 | 
				
			||||||
  -clang-diagnostic-unused-variable,
 | 
					 | 
				
			||||||
  -clang-diagnostic-unused-const-variable,
 | 
					  -clang-diagnostic-unused-const-variable,
 | 
				
			||||||
 | 
					  -clang-diagnostic-unused-parameter,
 | 
				
			||||||
  -concurrency-*,
 | 
					  -concurrency-*,
 | 
				
			||||||
  -cppcoreguidelines-avoid-c-arrays,
 | 
					  -cppcoreguidelines-avoid-c-arrays,
 | 
				
			||||||
  -cppcoreguidelines-avoid-goto,
 | 
					 | 
				
			||||||
  -cppcoreguidelines-avoid-magic-numbers,
 | 
					  -cppcoreguidelines-avoid-magic-numbers,
 | 
				
			||||||
  -cppcoreguidelines-init-variables,
 | 
					  -cppcoreguidelines-init-variables,
 | 
				
			||||||
  -cppcoreguidelines-macro-usage,
 | 
					  -cppcoreguidelines-macro-usage,
 | 
				
			||||||
@@ -41,7 +36,6 @@ Checks: >-
 | 
				
			|||||||
  -cppcoreguidelines-pro-type-union-access,
 | 
					  -cppcoreguidelines-pro-type-union-access,
 | 
				
			||||||
  -cppcoreguidelines-pro-type-vararg,
 | 
					  -cppcoreguidelines-pro-type-vararg,
 | 
				
			||||||
  -cppcoreguidelines-special-member-functions,
 | 
					  -cppcoreguidelines-special-member-functions,
 | 
				
			||||||
  -fuchsia-default-arguments,
 | 
					 | 
				
			||||||
  -fuchsia-multiple-inheritance,
 | 
					  -fuchsia-multiple-inheritance,
 | 
				
			||||||
  -fuchsia-overloaded-operator,
 | 
					  -fuchsia-overloaded-operator,
 | 
				
			||||||
  -fuchsia-statically-constructed-objects,
 | 
					  -fuchsia-statically-constructed-objects,
 | 
				
			||||||
@@ -51,6 +45,7 @@ Checks: >-
 | 
				
			|||||||
  -google-explicit-constructor,
 | 
					  -google-explicit-constructor,
 | 
				
			||||||
  -google-readability-braces-around-statements,
 | 
					  -google-readability-braces-around-statements,
 | 
				
			||||||
  -google-readability-casting,
 | 
					  -google-readability-casting,
 | 
				
			||||||
 | 
					  -google-readability-namespace-comments,
 | 
				
			||||||
  -google-readability-todo,
 | 
					  -google-readability-todo,
 | 
				
			||||||
  -google-runtime-references,
 | 
					  -google-runtime-references,
 | 
				
			||||||
  -hicpp-*,
 | 
					  -hicpp-*,
 | 
				
			||||||
@@ -73,8 +68,6 @@ Checks: >-
 | 
				
			|||||||
  -modernize-use-nodiscard,
 | 
					  -modernize-use-nodiscard,
 | 
				
			||||||
  -mpi-*,
 | 
					  -mpi-*,
 | 
				
			||||||
  -objc-*,
 | 
					  -objc-*,
 | 
				
			||||||
  -readability-braces-around-statements,
 | 
					 | 
				
			||||||
  -readability-const-return-type,
 | 
					 | 
				
			||||||
  -readability-convert-member-functions-to-static,
 | 
					  -readability-convert-member-functions-to-static,
 | 
				
			||||||
  -readability-else-after-return,
 | 
					  -readability-else-after-return,
 | 
				
			||||||
  -readability-function-cognitive-complexity,
 | 
					  -readability-function-cognitive-complexity,
 | 
				
			||||||
@@ -82,10 +75,6 @@ Checks: >-
 | 
				
			|||||||
  -readability-isolate-declaration,
 | 
					  -readability-isolate-declaration,
 | 
				
			||||||
  -readability-magic-numbers,
 | 
					  -readability-magic-numbers,
 | 
				
			||||||
  -readability-make-member-function-const,
 | 
					  -readability-make-member-function-const,
 | 
				
			||||||
  -readability-named-parameter,
 | 
					 | 
				
			||||||
  -readability-qualified-auto,
 | 
					 | 
				
			||||||
  -readability-redundant-access-specifiers,
 | 
					 | 
				
			||||||
  -readability-redundant-member-init,
 | 
					 | 
				
			||||||
  -readability-redundant-string-init,
 | 
					  -readability-redundant-string-init,
 | 
				
			||||||
  -readability-uppercase-literal-suffix,
 | 
					  -readability-uppercase-literal-suffix,
 | 
				
			||||||
  -readability-use-anyofallof,
 | 
					  -readability-use-anyofallof,
 | 
				
			||||||
@@ -97,9 +86,11 @@ CheckOptions:
 | 
				
			|||||||
    value:           '1'
 | 
					    value:           '1'
 | 
				
			||||||
  - key:             google-readability-function-size.StatementThreshold
 | 
					  - key:             google-readability-function-size.StatementThreshold
 | 
				
			||||||
    value:           '800'
 | 
					    value:           '800'
 | 
				
			||||||
  - key:             google-readability-namespace-comments.ShortNamespaceLines
 | 
					  - key:             google-runtime-int.TypeSuffix
 | 
				
			||||||
 | 
					    value:           '_t'
 | 
				
			||||||
 | 
					  - key:             llvm-namespace-comment.ShortNamespaceLines
 | 
				
			||||||
    value:           '10'
 | 
					    value:           '10'
 | 
				
			||||||
  - key:             google-readability-namespace-comments.SpacesBeforeComments
 | 
					  - key:             llvm-namespace-comment.SpacesBeforeComments
 | 
				
			||||||
    value:           '2'
 | 
					    value:           '2'
 | 
				
			||||||
  - key:             modernize-loop-convert.MaxCopySize
 | 
					  - key:             modernize-loop-convert.MaxCopySize
 | 
				
			||||||
    value:           '16'
 | 
					    value:           '16'
 | 
				
			||||||
@@ -117,6 +108,8 @@ CheckOptions:
 | 
				
			|||||||
    value:           'make_unique'
 | 
					    value:           'make_unique'
 | 
				
			||||||
  - key:             modernize-make-unique.MakeSmartPtrFunctionHeader
 | 
					  - key:             modernize-make-unique.MakeSmartPtrFunctionHeader
 | 
				
			||||||
    value:           'esphome/core/helpers.h'
 | 
					    value:           'esphome/core/helpers.h'
 | 
				
			||||||
 | 
					  - key:             readability-braces-around-statements.ShortStatementLines
 | 
				
			||||||
 | 
					    value:           2
 | 
				
			||||||
  - key:             readability-identifier-naming.LocalVariableCase
 | 
					  - key:             readability-identifier-naming.LocalVariableCase
 | 
				
			||||||
    value:           'lower_case'
 | 
					    value:           'lower_case'
 | 
				
			||||||
  - key:             readability-identifier-naming.ClassCase
 | 
					  - key:             readability-identifier-naming.ClassCase
 | 
				
			||||||
@@ -163,3 +156,5 @@ CheckOptions:
 | 
				
			|||||||
    value:           'lower_case'
 | 
					    value:           'lower_case'
 | 
				
			||||||
  - key:             readability-identifier-naming.VirtualMethodSuffix
 | 
					  - key:             readability-identifier-naming.VirtualMethodSuffix
 | 
				
			||||||
    value:           ''
 | 
					    value:           ''
 | 
				
			||||||
 | 
					  - key:             readability-qualified-auto.AddConstToQualified
 | 
				
			||||||
 | 
					    value:           0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "ESPHome Dev",
 | 
					  "name": "ESPHome Dev",
 | 
				
			||||||
  "image": "esphome/esphome-lint:dev",
 | 
					  "image": "ghcr.io/esphome/esphome-lint:dev",
 | 
				
			||||||
  "postCreateCommand": [
 | 
					  "postCreateCommand": [
 | 
				
			||||||
    "script/devcontainer-post-create"
 | 
					    "script/devcontainer-post-create"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,10 +25,9 @@ indent_size = 2
 | 
				
			|||||||
[*.{yaml,yml}]
 | 
					[*.{yaml,yml}]
 | 
				
			||||||
indent_style = space
 | 
					indent_style = space
 | 
				
			||||||
indent_size = 2
 | 
					indent_size = 2
 | 
				
			||||||
quote_type = single
 | 
					quote_type = double
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# JSON
 | 
					# JSON
 | 
				
			||||||
[*.json]
 | 
					[*.json]
 | 
				
			||||||
indent_style = space
 | 
					indent_style = space
 | 
				
			||||||
indent_size = 2
 | 
					indent_size = 2
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
# These are supported funding model platforms
 | 
					# These are supported funding model platforms
 | 
				
			||||||
 | 
					
 | 
				
			||||||
custom: https://www.nabucasa.com
 | 
					custom: https://www.nabucasa.com
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.github/ISSUE_TEMPLATE/config.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,4 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
blank_issues_enabled: false
 | 
					blank_issues_enabled: false
 | 
				
			||||||
contact_links:
 | 
					contact_links:
 | 
				
			||||||
  - name: Issue Tracker
 | 
					  - name: Issue Tracker
 | 
				
			||||||
@@ -5,8 +6,10 @@ contact_links:
 | 
				
			|||||||
    about: Please create bug reports in the dedicated issue tracker.
 | 
					    about: Please create bug reports in the dedicated issue tracker.
 | 
				
			||||||
  - name: Feature Request Tracker
 | 
					  - name: Feature Request Tracker
 | 
				
			||||||
    url: https://github.com/esphome/feature-requests
 | 
					    url: https://github.com/esphome/feature-requests
 | 
				
			||||||
    about: Please create feature requests in the dedicated feature request tracker.
 | 
					    about: |
 | 
				
			||||||
 | 
					      Please create feature requests in the dedicated feature request tracker.
 | 
				
			||||||
  - name: Frequently Asked Question
 | 
					  - name: Frequently Asked Question
 | 
				
			||||||
    url: https://esphome.io/guides/faq.html
 | 
					    url: https://esphome.io/guides/faq.html
 | 
				
			||||||
    about: Please view the FAQ for common questions and what to include in a bug report.
 | 
					    about: |
 | 
				
			||||||
    
 | 
					      Please view the FAQ for common questions and what
 | 
				
			||||||
 | 
					      to include in a bug report.
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										7
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/PULL_REQUEST_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
# What does this implement/fix? 
 | 
					# What does this implement/fix?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Quick description and explanation of changes
 | 
					<!-- Quick description and explanation of changes -->
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Types of changes
 | 
					## Types of changes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -18,6 +18,7 @@ Quick description and explanation of changes
 | 
				
			|||||||
- [ ] ESP32
 | 
					- [ ] ESP32
 | 
				
			||||||
- [ ] ESP32 IDF
 | 
					- [ ] ESP32 IDF
 | 
				
			||||||
- [ ] ESP8266
 | 
					- [ ] ESP8266
 | 
				
			||||||
 | 
					- [ ] RP2040
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Example entry for `config.yaml`:
 | 
					## Example entry for `config.yaml`:
 | 
				
			||||||
<!--
 | 
					<!--
 | 
				
			||||||
@@ -35,6 +36,6 @@ Quick description and explanation of changes
 | 
				
			|||||||
## Checklist:
 | 
					## Checklist:
 | 
				
			||||||
  - [ ] The code change is tested and works locally.
 | 
					  - [ ] The code change is tested and works locally.
 | 
				
			||||||
  - [ ] Tests have been added to verify that the new code works (under `tests/` folder).
 | 
					  - [ ] Tests have been added to verify that the new code works (under `tests/` folder).
 | 
				
			||||||
  
 | 
					
 | 
				
			||||||
If user exposed functionality or configuration variables are added/changed:
 | 
					If user exposed functionality or configuration variables are added/changed:
 | 
				
			||||||
  - [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs).
 | 
					  - [ ] Documentation added/updated in [esphome-docs](https://github.com/esphome/esphome-docs).
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,9 +1,15 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
version: 2
 | 
					version: 2
 | 
				
			||||||
updates:
 | 
					updates:
 | 
				
			||||||
  - package-ecosystem: "pip"
 | 
					  - package-ecosystem: pip
 | 
				
			||||||
    directory: "/"
 | 
					    directory: "/"
 | 
				
			||||||
    schedule:
 | 
					    schedule:
 | 
				
			||||||
      interval: "daily"
 | 
					      interval: daily
 | 
				
			||||||
    ignore:
 | 
					    ignore:
 | 
				
			||||||
      # Hypotehsis is only used for testing and is updated quite often
 | 
					      # Hypotehsis is only used for testing and is updated quite often
 | 
				
			||||||
      - dependency-name: hypothesis
 | 
					      - dependency-name: hypothesis
 | 
				
			||||||
 | 
					  - package-ecosystem: github-actions
 | 
				
			||||||
 | 
					    directory: "/"
 | 
				
			||||||
 | 
					    schedule:
 | 
				
			||||||
 | 
					      interval: daily
 | 
				
			||||||
 | 
					    open-pull-requests-limit: 10
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										57
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										57
									
								
								.github/workflows/ci-docker.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,21 +1,23 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
name: CI for docker images
 | 
					name: CI for docker images
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Only run when docker paths change
 | 
					# Only run when docker paths change
 | 
				
			||||||
 | 
					# yamllint disable-line rule:truthy
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  push:
 | 
					  push:
 | 
				
			||||||
    branches: [dev, beta, release]
 | 
					    branches: [dev, beta, release]
 | 
				
			||||||
    paths:
 | 
					    paths:
 | 
				
			||||||
      - 'docker/**'
 | 
					      - "docker/**"
 | 
				
			||||||
      - '.github/workflows/**'
 | 
					      - ".github/workflows/**"
 | 
				
			||||||
      - 'requirements*.txt'
 | 
					      - "requirements*.txt"
 | 
				
			||||||
      - 'platformio.ini'
 | 
					      - "platformio.ini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pull_request:
 | 
					  pull_request:
 | 
				
			||||||
    paths:
 | 
					    paths:
 | 
				
			||||||
      - 'docker/**'
 | 
					      - "docker/**"
 | 
				
			||||||
      - '.github/workflows/**'
 | 
					      - ".github/workflows/**"
 | 
				
			||||||
      - 'requirements*.txt'
 | 
					      - "requirements*.txt"
 | 
				
			||||||
      - 'platformio.ini'
 | 
					      - "platformio.ini"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					permissions:
 | 
				
			||||||
  contents: read
 | 
					  contents: read
 | 
				
			||||||
@@ -26,28 +28,29 @@ jobs:
 | 
				
			|||||||
    name: Build docker containers
 | 
					    name: Build docker containers
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
 | 
					      fail-fast: false
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        arch: [amd64, armv7, aarch64]
 | 
					        arch: [amd64, armv7, aarch64]
 | 
				
			||||||
        build_type: ["ha-addon", "docker", "lint"]
 | 
					        build_type: ["ha-addon", "docker", "lint"]
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
    - name: Set up Python
 | 
					      - name: Set up Python
 | 
				
			||||||
      uses: actions/setup-python@v2
 | 
					        uses: actions/setup-python@v4
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        python-version: '3.9'
 | 
					          python-version: "3.9"
 | 
				
			||||||
    - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
      uses: docker/setup-buildx-action@v1
 | 
					        uses: docker/setup-buildx-action@v2
 | 
				
			||||||
    - name: Set up QEMU
 | 
					      - name: Set up QEMU
 | 
				
			||||||
      uses: docker/setup-qemu-action@v1
 | 
					        uses: docker/setup-qemu-action@v2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Set TAG
 | 
					      - name: Set TAG
 | 
				
			||||||
      run: |
 | 
					        run: |
 | 
				
			||||||
        echo "TAG=check" >> $GITHUB_ENV
 | 
					          echo "TAG=check" >> $GITHUB_ENV
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Run build
 | 
					      - name: Run build
 | 
				
			||||||
      run: |
 | 
					        run: |
 | 
				
			||||||
        docker/build.py \
 | 
					          docker/build.py \
 | 
				
			||||||
          --tag "${TAG}" \
 | 
					            --tag "${TAG}" \
 | 
				
			||||||
          --arch "${{ matrix.arch }}" \
 | 
					            --arch "${{ matrix.arch }}" \
 | 
				
			||||||
          --build-type "${{ matrix.build_type }}" \
 | 
					            --build-type "${{ matrix.build_type }}" \
 | 
				
			||||||
          build
 | 
					            build
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										84
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,7 +1,7 @@
 | 
				
			|||||||
# THESE JOBS ARE COPIED IN release.yml and release-dev.yml
 | 
					---
 | 
				
			||||||
# PLEASE ALSO UPDATE THOSE FILES WHEN CHANGING LINES HERE
 | 
					 | 
				
			||||||
name: CI
 | 
					name: CI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# yamllint disable-line rule:truthy
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  push:
 | 
					  push:
 | 
				
			||||||
    branches: [dev, beta, release]
 | 
					    branches: [dev, beta, release]
 | 
				
			||||||
@@ -11,6 +11,11 @@ on:
 | 
				
			|||||||
permissions:
 | 
					permissions:
 | 
				
			||||||
  contents: read
 | 
					  contents: read
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					concurrency:
 | 
				
			||||||
 | 
					  # yamllint disable-line rule:line-length
 | 
				
			||||||
 | 
					  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
 | 
				
			||||||
 | 
					  cancel-in-progress: true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
jobs:
 | 
					jobs:
 | 
				
			||||||
  ci:
 | 
					  ci:
 | 
				
			||||||
    name: ${{ matrix.name }}
 | 
					    name: ${{ matrix.name }}
 | 
				
			||||||
@@ -34,7 +39,7 @@ jobs:
 | 
				
			|||||||
          - id: test
 | 
					          - id: test
 | 
				
			||||||
            file: tests/test3.yaml
 | 
					            file: tests/test3.yaml
 | 
				
			||||||
            name: Test tests/test3.yaml
 | 
					            name: Test tests/test3.yaml
 | 
				
			||||||
            pio_cache_key: test1
 | 
					            pio_cache_key: test3
 | 
				
			||||||
          - id: test
 | 
					          - id: test
 | 
				
			||||||
            file: tests/test4.yaml
 | 
					            file: tests/test4.yaml
 | 
				
			||||||
            name: Test tests/test4.yaml
 | 
					            name: Test tests/test4.yaml
 | 
				
			||||||
@@ -43,61 +48,76 @@ jobs:
 | 
				
			|||||||
            file: tests/test5.yaml
 | 
					            file: tests/test5.yaml
 | 
				
			||||||
            name: Test tests/test5.yaml
 | 
					            name: Test tests/test5.yaml
 | 
				
			||||||
            pio_cache_key: test5
 | 
					            pio_cache_key: test5
 | 
				
			||||||
 | 
					          - id: test
 | 
				
			||||||
 | 
					            file: tests/test6.yaml
 | 
				
			||||||
 | 
					            name: Test tests/test6.yaml
 | 
				
			||||||
 | 
					            pio_cache_key: test6
 | 
				
			||||||
          - id: pytest
 | 
					          - id: pytest
 | 
				
			||||||
            name: Run pytest
 | 
					            name: Run pytest
 | 
				
			||||||
          - id: clang-format
 | 
					          - id: clang-format
 | 
				
			||||||
            name: Run script/clang-format
 | 
					            name: Run script/clang-format
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP8266
 | 
					            name: Run script/clang-tidy for ESP8266
 | 
				
			||||||
            options: --environment esp8266-tidy --grep USE_ESP8266
 | 
					            options: --environment esp8266-arduino-tidy --grep USE_ESP8266
 | 
				
			||||||
            pio_cache_key: tidyesp8266
 | 
					            pio_cache_key: tidyesp8266
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP32 1/4
 | 
					            name: Run script/clang-tidy for ESP32 Arduino 1/4
 | 
				
			||||||
            options: --environment esp32-tidy --split-num 4 --split-at 1
 | 
					            options: --environment esp32-arduino-tidy --split-num 4 --split-at 1
 | 
				
			||||||
            pio_cache_key: tidyesp32
 | 
					            pio_cache_key: tidyesp32
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP32 2/4
 | 
					            name: Run script/clang-tidy for ESP32 Arduino 2/4
 | 
				
			||||||
            options: --environment esp32-tidy --split-num 4 --split-at 2
 | 
					            options: --environment esp32-arduino-tidy --split-num 4 --split-at 2
 | 
				
			||||||
            pio_cache_key: tidyesp32
 | 
					            pio_cache_key: tidyesp32
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP32 3/4
 | 
					            name: Run script/clang-tidy for ESP32 Arduino 3/4
 | 
				
			||||||
            options: --environment esp32-tidy --split-num 4 --split-at 3
 | 
					            options: --environment esp32-arduino-tidy --split-num 4 --split-at 3
 | 
				
			||||||
            pio_cache_key: tidyesp32
 | 
					            pio_cache_key: tidyesp32
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP32 4/4
 | 
					            name: Run script/clang-tidy for ESP32 Arduino 4/4
 | 
				
			||||||
            options: --environment esp32-tidy --split-num 4 --split-at 4
 | 
					            options: --environment esp32-arduino-tidy --split-num 4 --split-at 4
 | 
				
			||||||
            pio_cache_key: tidyesp32
 | 
					            pio_cache_key: tidyesp32
 | 
				
			||||||
          - id: clang-tidy
 | 
					          - id: clang-tidy
 | 
				
			||||||
            name: Run script/clang-tidy for ESP32 esp-idf
 | 
					            name: Run script/clang-tidy for ESP32 IDF
 | 
				
			||||||
            options: --environment esp32-idf-tidy --grep USE_ESP_IDF
 | 
					            options: --environment esp32-idf-tidy --grep USE_ESP_IDF
 | 
				
			||||||
            pio_cache_key: tidyesp32-idf
 | 
					            pio_cache_key: tidyesp32-idf
 | 
				
			||||||
 | 
					          - id: yamllint
 | 
				
			||||||
 | 
					            name: Run yamllint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
      - name: Set up Python
 | 
					      - name: Set up Python
 | 
				
			||||||
        uses: actions/setup-python@v2
 | 
					        uses: actions/setup-python@v4
 | 
				
			||||||
        id: python
 | 
					        id: python
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          python-version: '3.7'
 | 
					          python-version: "3.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Cache pip modules
 | 
					      - name: Cache virtualenv
 | 
				
			||||||
        uses: actions/cache@v2
 | 
					        uses: actions/cache@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          path: ~/.cache/pip
 | 
					          path: .venv
 | 
				
			||||||
          key: pip-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements*.txt') }}
 | 
					          # yamllint disable-line rule:line-length
 | 
				
			||||||
 | 
					          key: venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements*.txt') }}
 | 
				
			||||||
          restore-keys: |
 | 
					          restore-keys: |
 | 
				
			||||||
            pip-${{ steps.python.outputs.python-version }}-
 | 
					            venv-${{ steps.python.outputs.python-version }}-
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Set up python environment
 | 
					      - name: Set up virtualenv
 | 
				
			||||||
 | 
					        # yamllint disable rule:line-length
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          pip3 install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
 | 
					          python -m venv .venv
 | 
				
			||||||
          pip3 install -e .
 | 
					          source .venv/bin/activate
 | 
				
			||||||
 | 
					          pip install -U pip
 | 
				
			||||||
 | 
					          pip install -r requirements.txt -r requirements_optional.txt -r requirements_test.txt
 | 
				
			||||||
 | 
					          pip install -e .
 | 
				
			||||||
 | 
					          echo "$GITHUB_WORKSPACE/.venv/bin" >> $GITHUB_PATH
 | 
				
			||||||
 | 
					          echo "VIRTUAL_ENV=$GITHUB_WORKSPACE/.venv" >> $GITHUB_ENV
 | 
				
			||||||
 | 
					        # yamllint enable rule:line-length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # Use per check platformio cache because checks use different parts
 | 
					      # Use per check platformio cache because checks use different parts
 | 
				
			||||||
      - name: Cache platformio
 | 
					      - name: Cache platformio
 | 
				
			||||||
        uses: actions/cache@v2
 | 
					        uses: actions/cache@v3
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          path: ~/.platformio
 | 
					          path: ~/.platformio
 | 
				
			||||||
 | 
					          # yamllint disable-line rule:line-length
 | 
				
			||||||
          key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
 | 
					          key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
 | 
				
			||||||
        if: matrix.id == 'test' || matrix.id == 'clang-tidy'
 | 
					        if: matrix.id == 'test' || matrix.id == 'clang-tidy'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -124,7 +144,7 @@ jobs:
 | 
				
			|||||||
        if: matrix.id == 'ci-custom'
 | 
					        if: matrix.id == 'ci-custom'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Lint Python
 | 
					      - name: Lint Python
 | 
				
			||||||
        run: script/lint-python
 | 
					        run: script/lint-python -a
 | 
				
			||||||
        if: matrix.id == 'lint-python'
 | 
					        if: matrix.id == 'lint-python'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - run: esphome compile ${{ matrix.file }}
 | 
					      - run: esphome compile ${{ matrix.file }}
 | 
				
			||||||
@@ -138,8 +158,9 @@ jobs:
 | 
				
			|||||||
          pytest -vv --tb=native tests
 | 
					          pytest -vv --tb=native tests
 | 
				
			||||||
        if: matrix.id == 'pytest'
 | 
					        if: matrix.id == 'pytest'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # Also run git-diff-index so that the step is marked as failed on formatting errors,
 | 
					      # Also run git-diff-index so that the step is marked as failed on
 | 
				
			||||||
      # since clang-format doesn't do anything but change files if -i is passed.
 | 
					      # formatting errors, since clang-format doesn't do anything but
 | 
				
			||||||
 | 
					      # change files if -i is passed.
 | 
				
			||||||
      - name: Run clang-format
 | 
					      - name: Run clang-format
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          script/clang-format -i
 | 
					          script/clang-format -i
 | 
				
			||||||
@@ -154,6 +175,11 @@ jobs:
 | 
				
			|||||||
          # Also cache libdeps, store them in a ~/.platformio subfolder
 | 
					          # Also cache libdeps, store them in a ~/.platformio subfolder
 | 
				
			||||||
          PLATFORMIO_LIBDEPS_DIR: ~/.platformio/libdeps
 | 
					          PLATFORMIO_LIBDEPS_DIR: ~/.platformio/libdeps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Run yamllint
 | 
				
			||||||
 | 
					        if: matrix.id == 'yamllint'
 | 
				
			||||||
 | 
					        uses: frenck/action-yamllint@v1.3.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Suggested changes
 | 
					      - name: Suggested changes
 | 
				
			||||||
        run: script/ci-suggest-changes
 | 
					        run: script/ci-suggest-changes
 | 
				
			||||||
        if: always() && (matrix.id == 'clang-tidy' || matrix.id == 'clang-format')
 | 
					        # yamllint disable-line rule:line-length
 | 
				
			||||||
 | 
					        if: always() && (matrix.id == 'clang-tidy' || matrix.id == 'clang-format' || matrix.id == 'lint-python')
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								.github/workflows/lock.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.github/workflows/lock.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +1,10 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
name: Lock
 | 
					name: Lock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# yamllint disable-line rule:truthy
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  schedule:
 | 
					  schedule:
 | 
				
			||||||
    - cron: '30 0 * * *'
 | 
					    - cron: "30 0 * * *"
 | 
				
			||||||
  workflow_dispatch:
 | 
					  workflow_dispatch:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					permissions:
 | 
				
			||||||
@@ -16,7 +18,7 @@ jobs:
 | 
				
			|||||||
  lock:
 | 
					  lock:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: dessant/lock-threads@v3
 | 
					      - uses: dessant/lock-threads@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          pr-inactive-days: "1"
 | 
					          pr-inactive-days: "1"
 | 
				
			||||||
          pr-lock-reason: ""
 | 
					          pr-lock-reason: ""
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/matchers/ci-custom.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/matchers/ci-custom.json
									
									
									
									
										vendored
									
									
								
							@@ -4,7 +4,7 @@
 | 
				
			|||||||
            "owner": "ci-custom",
 | 
					            "owner": "ci-custom",
 | 
				
			||||||
            "pattern": [
 | 
					            "pattern": [
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    "regexp": "^ERROR (.*):(\\d+):(\\d+) - (.*)$",
 | 
					                    "regexp": "^(.*):(\\d+):(\\d+):\\s+lint:\\s+(.*)$",
 | 
				
			||||||
                    "file": 1,
 | 
					                    "file": 1,
 | 
				
			||||||
                    "line": 2,
 | 
					                    "line": 2,
 | 
				
			||||||
                    "column": 3,
 | 
					                    "column": 3,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								.github/workflows/matchers/gcc.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/matchers/gcc.json
									
									
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@
 | 
				
			|||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "regexp": "^(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
 | 
					          "regexp": "^src/(.*):(\\d+):(\\d+):\\s+(?:fatal\\s+)?(warning|error):\\s+(.*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "column": 3,
 | 
					          "column": 3,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								.github/workflows/matchers/lint-python.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/matchers/lint-python.json
									
									
									
									
										vendored
									
									
								
							@@ -1,11 +1,22 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "problemMatcher": [
 | 
					  "problemMatcher": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "owner": "black",
 | 
				
			||||||
 | 
					      "severity": "error",
 | 
				
			||||||
 | 
					      "pattern": [
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          "regexp": "^(.*): (Please format this file with the black formatter)",
 | 
				
			||||||
 | 
					          "file": 1,
 | 
				
			||||||
 | 
					          "message": 2
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "owner": "flake8",
 | 
					      "owner": "flake8",
 | 
				
			||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
          "regexp": "^(.*):(\\d+) - ([EFCDNW]\\d{3}.*)$",
 | 
					          "regexp": "^(.*):(\\d+): ([EFCDNW]\\d{3}.*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "message": 3
 | 
					          "message": 3
 | 
				
			||||||
@@ -17,7 +28,7 @@
 | 
				
			|||||||
      "severity": "error",
 | 
					      "severity": "error",
 | 
				
			||||||
      "pattern": [
 | 
					      "pattern": [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          "regexp": "^(.*):(\\d+) - (\\[[EFCRW]\\d{4}\\(.*\\),.*\\].*)$",
 | 
					          "regexp": "^(.*):(\\d+): (\\[[EFCRW]\\d{4}\\(.*\\),.*\\].*)$",
 | 
				
			||||||
          "file": 1,
 | 
					          "file": 1,
 | 
				
			||||||
          "line": 2,
 | 
					          "line": 2,
 | 
				
			||||||
          "message": 3
 | 
					          "message": 3
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										118
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										118
									
								
								.github/workflows/release.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,5 +1,7 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
name: Publish Release
 | 
					name: Publish Release
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# yamllint disable-line rule:truthy
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  workflow_dispatch:
 | 
					  workflow_dispatch:
 | 
				
			||||||
  release:
 | 
					  release:
 | 
				
			||||||
@@ -17,9 +19,10 @@ jobs:
 | 
				
			|||||||
    outputs:
 | 
					    outputs:
 | 
				
			||||||
      tag: ${{ steps.tag.outputs.tag }}
 | 
					      tag: ${{ steps.tag.outputs.tag }}
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
      - name: Get tag
 | 
					      - name: Get tag
 | 
				
			||||||
        id: tag
 | 
					        id: tag
 | 
				
			||||||
 | 
					        # yamllint disable rule:line-length
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          if [[ "$GITHUB_EVENT_NAME" = "release" ]]; then
 | 
					          if [[ "$GITHUB_EVENT_NAME" = "release" ]]; then
 | 
				
			||||||
            TAG="${GITHUB_REF#refs/tags/}"
 | 
					            TAG="${GITHUB_REF#refs/tags/}"
 | 
				
			||||||
@@ -28,18 +31,19 @@ jobs:
 | 
				
			|||||||
            today="$(date --utc '+%Y%m%d')"
 | 
					            today="$(date --utc '+%Y%m%d')"
 | 
				
			||||||
            TAG="${TAG}${today}"
 | 
					            TAG="${TAG}${today}"
 | 
				
			||||||
          fi
 | 
					          fi
 | 
				
			||||||
          echo "::set-output name=tag::${TAG}"
 | 
					          echo "tag=${TAG}" >> $GITHUB_OUTPUT
 | 
				
			||||||
 | 
					        # yamllint enable rule:line-length
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  deploy-pypi:
 | 
					  deploy-pypi:
 | 
				
			||||||
    name: Build and publish to PyPi
 | 
					    name: Build and publish to PyPi
 | 
				
			||||||
    if: github.repository == 'esphome/esphome' && github.event_name == 'release'
 | 
					    if: github.repository == 'esphome/esphome' && github.event_name == 'release'
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
      - name: Set up Python
 | 
					      - name: Set up Python
 | 
				
			||||||
        uses: actions/setup-python@v1
 | 
					        uses: actions/setup-python@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          python-version: '3.x'
 | 
					          python-version: "3.x"
 | 
				
			||||||
      - name: Set up python environment
 | 
					      - name: Set up python environment
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          script/setup
 | 
					          script/setup
 | 
				
			||||||
@@ -65,37 +69,37 @@ jobs:
 | 
				
			|||||||
        arch: [amd64, armv7, aarch64]
 | 
					        arch: [amd64, armv7, aarch64]
 | 
				
			||||||
        build_type: ["ha-addon", "docker", "lint"]
 | 
					        build_type: ["ha-addon", "docker", "lint"]
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
    - name: Set up Python
 | 
					      - name: Set up Python
 | 
				
			||||||
      uses: actions/setup-python@v2
 | 
					        uses: actions/setup-python@v4
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        python-version: '3.9'
 | 
					          python-version: "3.9"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Set up Docker Buildx
 | 
					      - name: Set up Docker Buildx
 | 
				
			||||||
      uses: docker/setup-buildx-action@v1
 | 
					        uses: docker/setup-buildx-action@v2
 | 
				
			||||||
    - name: Set up QEMU
 | 
					      - name: Set up QEMU
 | 
				
			||||||
      uses: docker/setup-qemu-action@v1
 | 
					        uses: docker/setup-qemu-action@v2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Log in to docker hub
 | 
					      - name: Log in to docker hub
 | 
				
			||||||
      uses: docker/login-action@v1
 | 
					        uses: docker/login-action@v2
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        username: ${{ secrets.DOCKER_USER }}
 | 
					          username: ${{ secrets.DOCKER_USER }}
 | 
				
			||||||
        password: ${{ secrets.DOCKER_PASSWORD }}
 | 
					          password: ${{ secrets.DOCKER_PASSWORD }}
 | 
				
			||||||
    - name: Log in to the GitHub container registry
 | 
					      - name: Log in to the GitHub container registry
 | 
				
			||||||
      uses: docker/login-action@v1
 | 
					        uses: docker/login-action@v2
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
          registry: ghcr.io
 | 
					          registry: ghcr.io
 | 
				
			||||||
          username: ${{ github.actor }}
 | 
					          username: ${{ github.actor }}
 | 
				
			||||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
					          password: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Build and push
 | 
					      - name: Build and push
 | 
				
			||||||
      run: |
 | 
					        run: |
 | 
				
			||||||
        docker/build.py \
 | 
					          docker/build.py \
 | 
				
			||||||
          --tag "${{ needs.init.outputs.tag }}" \
 | 
					            --tag "${{ needs.init.outputs.tag }}" \
 | 
				
			||||||
          --arch "${{ matrix.arch }}" \
 | 
					            --arch "${{ matrix.arch }}" \
 | 
				
			||||||
          --build-type "${{ matrix.build_type }}" \
 | 
					            --build-type "${{ matrix.build_type }}" \
 | 
				
			||||||
          build \
 | 
					            build \
 | 
				
			||||||
          --push
 | 
					            --push
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  deploy-docker-manifest:
 | 
					  deploy-docker-manifest:
 | 
				
			||||||
    if: github.repository == 'esphome/esphome'
 | 
					    if: github.repository == 'esphome/esphome'
 | 
				
			||||||
@@ -108,47 +112,49 @@ jobs:
 | 
				
			|||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        build_type: ["ha-addon", "docker", "lint"]
 | 
					        build_type: ["ha-addon", "docker", "lint"]
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
    - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v3
 | 
				
			||||||
    - name: Set up Python
 | 
					      - name: Set up Python
 | 
				
			||||||
      uses: actions/setup-python@v2
 | 
					        uses: actions/setup-python@v4
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        python-version: '3.9'
 | 
					          python-version: "3.9"
 | 
				
			||||||
    - name: Enable experimental manifest support
 | 
					      - name: Enable experimental manifest support
 | 
				
			||||||
      run: |
 | 
					        run: |
 | 
				
			||||||
        mkdir -p ~/.docker
 | 
					          mkdir -p ~/.docker
 | 
				
			||||||
        echo "{\"experimental\": \"enabled\"}" > ~/.docker/config.json
 | 
					          echo "{\"experimental\": \"enabled\"}" > ~/.docker/config.json
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Log in to docker hub
 | 
					      - name: Log in to docker hub
 | 
				
			||||||
      uses: docker/login-action@v1
 | 
					        uses: docker/login-action@v2
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
        username: ${{ secrets.DOCKER_USER }}
 | 
					          username: ${{ secrets.DOCKER_USER }}
 | 
				
			||||||
        password: ${{ secrets.DOCKER_PASSWORD }}
 | 
					          password: ${{ secrets.DOCKER_PASSWORD }}
 | 
				
			||||||
    - name: Log in to the GitHub container registry
 | 
					      - name: Log in to the GitHub container registry
 | 
				
			||||||
      uses: docker/login-action@v1
 | 
					        uses: docker/login-action@v2
 | 
				
			||||||
      with:
 | 
					        with:
 | 
				
			||||||
          registry: ghcr.io
 | 
					          registry: ghcr.io
 | 
				
			||||||
          username: ${{ github.actor }}
 | 
					          username: ${{ github.actor }}
 | 
				
			||||||
          password: ${{ secrets.GITHUB_TOKEN }}
 | 
					          password: ${{ secrets.GITHUB_TOKEN }}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    - name: Run manifest
 | 
					      - name: Run manifest
 | 
				
			||||||
      run: |
 | 
					        run: |
 | 
				
			||||||
        docker/build.py \
 | 
					          docker/build.py \
 | 
				
			||||||
          --tag "${{ needs.init.outputs.tag }}" \
 | 
					            --tag "${{ needs.init.outputs.tag }}" \
 | 
				
			||||||
          --build-type "${{ matrix.build_type }}" \
 | 
					            --build-type "${{ matrix.build_type }}" \
 | 
				
			||||||
          manifest
 | 
					            manifest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  deploy-hassio-repo:
 | 
					  deploy-ha-addon-repo:
 | 
				
			||||||
    if: github.repository == 'esphome/esphome' && github.event_name == 'release'
 | 
					    if: github.repository == 'esphome/esphome' && github.event_name == 'release'
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    needs: [deploy-docker]
 | 
					    needs: [deploy-docker]
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - env:
 | 
					      - env:
 | 
				
			||||||
          TOKEN: ${{ secrets.DEPLOY_HASSIO_TOKEN }}
 | 
					          TOKEN: ${{ secrets.DEPLOY_HA_ADDON_REPO_TOKEN }}
 | 
				
			||||||
 | 
					        # yamllint disable rule:line-length
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          TAG="${GITHUB_REF#refs/tags/}"
 | 
					          TAG="${GITHUB_REF#refs/tags/}"
 | 
				
			||||||
          curl \
 | 
					          curl \
 | 
				
			||||||
            -u ":$TOKEN" \
 | 
					            -u ":$TOKEN" \
 | 
				
			||||||
            -X POST \
 | 
					            -X POST \
 | 
				
			||||||
            -H "Accept: application/vnd.github.v3+json" \
 | 
					            -H "Accept: application/vnd.github.v3+json" \
 | 
				
			||||||
            https://api.github.com/repos/esphome/hassio/actions/workflows/bump-version.yml/dispatches \
 | 
					            https://api.github.com/repos/esphome/home-assistant-addon/actions/workflows/bump-version.yml/dispatches \
 | 
				
			||||||
            -d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$TAG\"}}"
 | 
					            -d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$TAG\"}}"
 | 
				
			||||||
 | 
					        # yamllint enable rule:line-length
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										11
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/workflows/stale.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,8 +1,10 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
name: Stale
 | 
					name: Stale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# yamllint disable-line rule:truthy
 | 
				
			||||||
on:
 | 
					on:
 | 
				
			||||||
  schedule:
 | 
					  schedule:
 | 
				
			||||||
    - cron: '30 0 * * *'
 | 
					    - cron: "30 0 * * *"
 | 
				
			||||||
  workflow_dispatch:
 | 
					  workflow_dispatch:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
permissions:
 | 
					permissions:
 | 
				
			||||||
@@ -16,7 +18,7 @@ jobs:
 | 
				
			|||||||
  stale:
 | 
					  stale:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/stale@v4
 | 
					      - uses: actions/stale@v6
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          days-before-pr-stale: 90
 | 
					          days-before-pr-stale: 90
 | 
				
			||||||
          days-before-pr-close: 7
 | 
					          days-before-pr-close: 7
 | 
				
			||||||
@@ -31,11 +33,12 @@ jobs:
 | 
				
			|||||||
            and will be closed if no further activity occurs within 7 days.
 | 
					            and will be closed if no further activity occurs within 7 days.
 | 
				
			||||||
            Thank you for your contributions.
 | 
					            Thank you for your contributions.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Use stale to automatically close issues with a reference to the issue tracker
 | 
					  # Use stale to automatically close issues with a
 | 
				
			||||||
 | 
					  # reference to the issue tracker
 | 
				
			||||||
  close-issues:
 | 
					  close-issues:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/stale@v4
 | 
					      - uses: actions/stale@v6
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          days-before-pr-stale: -1
 | 
					          days-before-pr-stale: -1
 | 
				
			||||||
          days-before-pr-close: -1
 | 
					          days-before-pr-close: -1
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -77,6 +77,7 @@ venv/
 | 
				
			|||||||
ENV/
 | 
					ENV/
 | 
				
			||||||
env.bak/
 | 
					env.bak/
 | 
				
			||||||
venv.bak/
 | 
					venv.bak/
 | 
				
			||||||
 | 
					venv-*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# mypy
 | 
					# mypy
 | 
				
			||||||
.mypy_cache/
 | 
					.mypy_cache/
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
ports:
 | 
					 | 
				
			||||||
- port: 6052
 | 
					 | 
				
			||||||
  onOpen: open-preview
 | 
					 | 
				
			||||||
tasks:
 | 
					 | 
				
			||||||
- before: pyenv local $(pyenv version | grep '^3\.' | cut -d ' ' -f 1) && script/setup
 | 
					 | 
				
			||||||
  command: python -m esphome config dashboard
 | 
					 | 
				
			||||||
@@ -1,16 +1,17 @@
 | 
				
			|||||||
 | 
					---
 | 
				
			||||||
# See https://pre-commit.com for more information
 | 
					# See https://pre-commit.com for more information
 | 
				
			||||||
# See https://pre-commit.com/hooks.html for more hooks
 | 
					# See https://pre-commit.com/hooks.html for more hooks
 | 
				
			||||||
repos:
 | 
					repos:
 | 
				
			||||||
  - repo: https://github.com/ambv/black
 | 
					  - repo: https://github.com/ambv/black
 | 
				
			||||||
    rev: 20.8b1
 | 
					    rev: 22.10.0
 | 
				
			||||||
    hooks:
 | 
					    hooks:
 | 
				
			||||||
    - id: black
 | 
					      - id: black
 | 
				
			||||||
      args:
 | 
					        args:
 | 
				
			||||||
        - --safe
 | 
					          - --safe
 | 
				
			||||||
        - --quiet
 | 
					          - --quiet
 | 
				
			||||||
      files: ^((esphome|script|tests)/.+)?[^/]+\.py$
 | 
					        files: ^((esphome|script|tests)/.+)?[^/]+\.py$
 | 
				
			||||||
  - repo: https://gitlab.com/pycqa/flake8
 | 
					  - repo: https://github.com/PyCQA/flake8
 | 
				
			||||||
    rev: 3.8.4
 | 
					    rev: 6.0.0
 | 
				
			||||||
    hooks:
 | 
					    hooks:
 | 
				
			||||||
      - id: flake8
 | 
					      - id: flake8
 | 
				
			||||||
        additional_dependencies:
 | 
					        additional_dependencies:
 | 
				
			||||||
@@ -25,3 +26,8 @@ repos:
 | 
				
			|||||||
          - --branch=dev
 | 
					          - --branch=dev
 | 
				
			||||||
          - --branch=release
 | 
					          - --branch=release
 | 
				
			||||||
          - --branch=beta
 | 
					          - --branch=beta
 | 
				
			||||||
 | 
					  - repo: https://github.com/asottile/pyupgrade
 | 
				
			||||||
 | 
					    rev: v3.3.0
 | 
				
			||||||
 | 
					    hooks:
 | 
				
			||||||
 | 
					      - id: pyupgrade
 | 
				
			||||||
 | 
					        args: [--py39-plus]
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										92
									
								
								CODEOWNERS
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								CODEOWNERS
									
									
									
									
									
								
							@@ -13,12 +13,14 @@ esphome/core/* @esphome/core
 | 
				
			|||||||
# Integrations
 | 
					# Integrations
 | 
				
			||||||
esphome/components/ac_dimmer/* @glmnet
 | 
					esphome/components/ac_dimmer/* @glmnet
 | 
				
			||||||
esphome/components/adc/* @esphome/core
 | 
					esphome/components/adc/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/adc128s102/* @DeerMaximum
 | 
				
			||||||
esphome/components/addressable_light/* @justfalter
 | 
					esphome/components/addressable_light/* @justfalter
 | 
				
			||||||
esphome/components/airthings_ble/* @jeromelaban
 | 
					esphome/components/airthings_ble/* @jeromelaban
 | 
				
			||||||
esphome/components/airthings_wave_mini/* @ncareau
 | 
					esphome/components/airthings_wave_mini/* @ncareau
 | 
				
			||||||
esphome/components/airthings_wave_plus/* @jeromelaban
 | 
					esphome/components/airthings_wave_plus/* @jeromelaban
 | 
				
			||||||
esphome/components/am43/* @buxtronix
 | 
					esphome/components/am43/* @buxtronix
 | 
				
			||||||
esphome/components/am43/cover/* @buxtronix
 | 
					esphome/components/am43/cover/* @buxtronix
 | 
				
			||||||
 | 
					esphome/components/analog_threshold/* @ianchi
 | 
				
			||||||
esphome/components/animation/* @syndlex
 | 
					esphome/components/animation/* @syndlex
 | 
				
			||||||
esphome/components/anova/* @buxtronix
 | 
					esphome/components/anova/* @buxtronix
 | 
				
			||||||
esphome/components/api/* @OttoWinter
 | 
					esphome/components/api/* @OttoWinter
 | 
				
			||||||
@@ -27,63 +29,99 @@ esphome/components/atc_mithermometer/* @ahpohl
 | 
				
			|||||||
esphome/components/b_parasite/* @rbaron
 | 
					esphome/components/b_parasite/* @rbaron
 | 
				
			||||||
esphome/components/ballu/* @bazuchan
 | 
					esphome/components/ballu/* @bazuchan
 | 
				
			||||||
esphome/components/bang_bang/* @OttoWinter
 | 
					esphome/components/bang_bang/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/bedjet/* @jhansche
 | 
				
			||||||
 | 
					esphome/components/bedjet/climate/* @jhansche
 | 
				
			||||||
 | 
					esphome/components/bedjet/fan/* @jhansche
 | 
				
			||||||
 | 
					esphome/components/bh1750/* @OttoWinter
 | 
				
			||||||
esphome/components/binary_sensor/* @esphome/core
 | 
					esphome/components/binary_sensor/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/bl0939/* @ziceva
 | 
				
			||||||
 | 
					esphome/components/bl0940/* @tobias-
 | 
				
			||||||
 | 
					esphome/components/bl0942/* @dbuezas
 | 
				
			||||||
esphome/components/ble_client/* @buxtronix
 | 
					esphome/components/ble_client/* @buxtronix
 | 
				
			||||||
 | 
					esphome/components/bluetooth_proxy/* @jesserockz
 | 
				
			||||||
esphome/components/bme680_bsec/* @trvrnrth
 | 
					esphome/components/bme680_bsec/* @trvrnrth
 | 
				
			||||||
 | 
					esphome/components/bmp3xx/* @martgras
 | 
				
			||||||
 | 
					esphome/components/button/* @esphome/core
 | 
				
			||||||
esphome/components/canbus/* @danielschramm @mvturnho
 | 
					esphome/components/canbus/* @danielschramm @mvturnho
 | 
				
			||||||
esphome/components/cap1188/* @MrEditor97
 | 
					esphome/components/cap1188/* @MrEditor97
 | 
				
			||||||
esphome/components/captive_portal/* @OttoWinter
 | 
					esphome/components/captive_portal/* @OttoWinter
 | 
				
			||||||
esphome/components/ccs811/* @habbie
 | 
					esphome/components/ccs811/* @habbie
 | 
				
			||||||
 | 
					esphome/components/cd74hc4067/* @asoehlke
 | 
				
			||||||
esphome/components/climate/* @esphome/core
 | 
					esphome/components/climate/* @esphome/core
 | 
				
			||||||
esphome/components/climate_ir/* @glmnet
 | 
					esphome/components/climate_ir/* @glmnet
 | 
				
			||||||
esphome/components/color_temperature/* @jesserockz
 | 
					esphome/components/color_temperature/* @jesserockz
 | 
				
			||||||
esphome/components/coolix/* @glmnet
 | 
					esphome/components/coolix/* @glmnet
 | 
				
			||||||
 | 
					esphome/components/copy/* @OttoWinter
 | 
				
			||||||
esphome/components/cover/* @esphome/core
 | 
					esphome/components/cover/* @esphome/core
 | 
				
			||||||
esphome/components/cs5460a/* @balrog-kun
 | 
					esphome/components/cs5460a/* @balrog-kun
 | 
				
			||||||
esphome/components/cse7761/* @berfenger
 | 
					esphome/components/cse7761/* @berfenger
 | 
				
			||||||
esphome/components/ct_clamp/* @jesserockz
 | 
					esphome/components/ct_clamp/* @jesserockz
 | 
				
			||||||
esphome/components/current_based/* @djwmarcx
 | 
					esphome/components/current_based/* @djwmarcx
 | 
				
			||||||
 | 
					esphome/components/dac7678/* @NickB1
 | 
				
			||||||
 | 
					esphome/components/daikin_brc/* @hagak
 | 
				
			||||||
esphome/components/daly_bms/* @s1lvi0
 | 
					esphome/components/daly_bms/* @s1lvi0
 | 
				
			||||||
esphome/components/dashboard_import/* @esphome/core
 | 
					esphome/components/dashboard_import/* @esphome/core
 | 
				
			||||||
esphome/components/debug/* @OttoWinter
 | 
					esphome/components/debug/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/delonghi/* @grob6000
 | 
				
			||||||
esphome/components/dfplayer/* @glmnet
 | 
					esphome/components/dfplayer/* @glmnet
 | 
				
			||||||
esphome/components/dht/* @OttoWinter
 | 
					esphome/components/dht/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/display_menu_base/* @numo68
 | 
				
			||||||
 | 
					esphome/components/dps310/* @kbx81
 | 
				
			||||||
esphome/components/ds1307/* @badbadc0ffee
 | 
					esphome/components/ds1307/* @badbadc0ffee
 | 
				
			||||||
esphome/components/dsmr/* @glmnet @zuidwijk
 | 
					esphome/components/dsmr/* @glmnet @zuidwijk
 | 
				
			||||||
 | 
					esphome/components/ektf2232/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/ens210/* @itn3rd77
 | 
				
			||||||
esphome/components/esp32/* @esphome/core
 | 
					esphome/components/esp32/* @esphome/core
 | 
				
			||||||
esphome/components/esp32_ble/* @jesserockz
 | 
					esphome/components/esp32_ble/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/esp32_ble_client/* @jesserockz
 | 
				
			||||||
esphome/components/esp32_ble_server/* @jesserockz
 | 
					esphome/components/esp32_ble_server/* @jesserockz
 | 
				
			||||||
esphome/components/esp32_camera_web_server/* @ayufan
 | 
					esphome/components/esp32_camera_web_server/* @ayufan
 | 
				
			||||||
 | 
					esphome/components/esp32_can/* @Sympatron
 | 
				
			||||||
esphome/components/esp32_improv/* @jesserockz
 | 
					esphome/components/esp32_improv/* @jesserockz
 | 
				
			||||||
esphome/components/esp8266/* @esphome/core
 | 
					esphome/components/esp8266/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/ethernet_info/* @gtjadsonsantos
 | 
				
			||||||
esphome/components/exposure_notifications/* @OttoWinter
 | 
					esphome/components/exposure_notifications/* @OttoWinter
 | 
				
			||||||
esphome/components/ezo/* @ssieb
 | 
					esphome/components/ezo/* @ssieb
 | 
				
			||||||
 | 
					esphome/components/ezo_pmp/* @carlos-sarmiento
 | 
				
			||||||
 | 
					esphome/components/factory_reset/* @anatoly-savchenkov
 | 
				
			||||||
esphome/components/fastled_base/* @OttoWinter
 | 
					esphome/components/fastled_base/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/feedback/* @ianchi
 | 
				
			||||||
esphome/components/fingerprint_grow/* @OnFreund @loongyh
 | 
					esphome/components/fingerprint_grow/* @OnFreund @loongyh
 | 
				
			||||||
esphome/components/globals/* @esphome/core
 | 
					esphome/components/globals/* @esphome/core
 | 
				
			||||||
esphome/components/gpio/* @esphome/core
 | 
					esphome/components/gpio/* @esphome/core
 | 
				
			||||||
esphome/components/gps/* @coogle
 | 
					esphome/components/gps/* @coogle
 | 
				
			||||||
esphome/components/graph/* @synco
 | 
					esphome/components/graph/* @synco
 | 
				
			||||||
 | 
					esphome/components/growatt_solar/* @leeuwte
 | 
				
			||||||
esphome/components/havells_solar/* @sourabhjaiswal
 | 
					esphome/components/havells_solar/* @sourabhjaiswal
 | 
				
			||||||
esphome/components/hbridge/fan/* @WeekendWarrior
 | 
					esphome/components/hbridge/fan/* @WeekendWarrior
 | 
				
			||||||
esphome/components/hbridge/light/* @DotNetDann
 | 
					esphome/components/hbridge/light/* @DotNetDann
 | 
				
			||||||
esphome/components/heatpumpir/* @rob-deutsch
 | 
					esphome/components/heatpumpir/* @rob-deutsch
 | 
				
			||||||
esphome/components/hitachi_ac424/* @sourabhjaiswal
 | 
					esphome/components/hitachi_ac424/* @sourabhjaiswal
 | 
				
			||||||
esphome/components/homeassistant/* @OttoWinter
 | 
					esphome/components/homeassistant/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/honeywellabp/* @RubyBailey
 | 
				
			||||||
esphome/components/hrxl_maxsonar_wr/* @netmikey
 | 
					esphome/components/hrxl_maxsonar_wr/* @netmikey
 | 
				
			||||||
 | 
					esphome/components/hydreon_rgxx/* @functionpointer
 | 
				
			||||||
esphome/components/i2c/* @esphome/core
 | 
					esphome/components/i2c/* @esphome/core
 | 
				
			||||||
esphome/components/improv/* @jesserockz
 | 
					esphome/components/i2s_audio/* @jesserockz
 | 
				
			||||||
esphome/components/improv_serial/* @esphome/core
 | 
					esphome/components/improv_serial/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/ina260/* @MrEditor97
 | 
				
			||||||
esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
					esphome/components/inkbird_ibsth1_mini/* @fkirill
 | 
				
			||||||
esphome/components/inkplate6/* @jesserockz
 | 
					esphome/components/inkplate6/* @jesserockz
 | 
				
			||||||
esphome/components/integration/* @OttoWinter
 | 
					esphome/components/integration/* @OttoWinter
 | 
				
			||||||
esphome/components/interval/* @esphome/core
 | 
					esphome/components/interval/* @esphome/core
 | 
				
			||||||
esphome/components/json/* @OttoWinter
 | 
					esphome/components/json/* @OttoWinter
 | 
				
			||||||
 | 
					esphome/components/kalman_combinator/* @Cat-Ion
 | 
				
			||||||
 | 
					esphome/components/lcd_menu/* @numo68
 | 
				
			||||||
esphome/components/ledc/* @OttoWinter
 | 
					esphome/components/ledc/* @OttoWinter
 | 
				
			||||||
esphome/components/light/* @esphome/core
 | 
					esphome/components/light/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/lilygo_t5_47/touchscreen/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/lock/* @esphome/core
 | 
				
			||||||
esphome/components/logger/* @esphome/core
 | 
					esphome/components/logger/* @esphome/core
 | 
				
			||||||
esphome/components/ltr390/* @sjtrny
 | 
					esphome/components/ltr390/* @sjtrny
 | 
				
			||||||
 | 
					esphome/components/max31865/* @DAVe3283
 | 
				
			||||||
 | 
					esphome/components/max44009/* @berfenger
 | 
				
			||||||
esphome/components/max7219digit/* @rspaargaren
 | 
					esphome/components/max7219digit/* @rspaargaren
 | 
				
			||||||
 | 
					esphome/components/max9611/* @mckaymatthew
 | 
				
			||||||
esphome/components/mcp23008/* @jesserockz
 | 
					esphome/components/mcp23008/* @jesserockz
 | 
				
			||||||
esphome/components/mcp23017/* @jesserockz
 | 
					esphome/components/mcp23017/* @jesserockz
 | 
				
			||||||
esphome/components/mcp23s08/* @SenexCrenshaw @jesserockz
 | 
					esphome/components/mcp23s08/* @SenexCrenshaw @jesserockz
 | 
				
			||||||
@@ -92,18 +130,30 @@ esphome/components/mcp23x08_base/* @jesserockz
 | 
				
			|||||||
esphome/components/mcp23x17_base/* @jesserockz
 | 
					esphome/components/mcp23x17_base/* @jesserockz
 | 
				
			||||||
esphome/components/mcp23xxx_base/* @jesserockz
 | 
					esphome/components/mcp23xxx_base/* @jesserockz
 | 
				
			||||||
esphome/components/mcp2515/* @danielschramm @mvturnho
 | 
					esphome/components/mcp2515/* @danielschramm @mvturnho
 | 
				
			||||||
 | 
					esphome/components/mcp3204/* @rsumner
 | 
				
			||||||
 | 
					esphome/components/mcp4728/* @berfenger
 | 
				
			||||||
 | 
					esphome/components/mcp47a1/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/mcp9600/* @MrEditor97
 | 
				
			||||||
esphome/components/mcp9808/* @k7hpn
 | 
					esphome/components/mcp9808/* @k7hpn
 | 
				
			||||||
esphome/components/md5/* @esphome/core
 | 
					esphome/components/md5/* @esphome/core
 | 
				
			||||||
esphome/components/mdns/* @esphome/core
 | 
					esphome/components/mdns/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/media_player/* @jesserockz
 | 
				
			||||||
esphome/components/midea/* @dudanov
 | 
					esphome/components/midea/* @dudanov
 | 
				
			||||||
 | 
					esphome/components/midea_ir/* @dudanov
 | 
				
			||||||
esphome/components/mitsubishi/* @RubyBailey
 | 
					esphome/components/mitsubishi/* @RubyBailey
 | 
				
			||||||
 | 
					esphome/components/mlx90393/* @functionpointer
 | 
				
			||||||
esphome/components/modbus_controller/* @martgras
 | 
					esphome/components/modbus_controller/* @martgras
 | 
				
			||||||
esphome/components/modbus_controller/binary_sensor/* @martgras
 | 
					esphome/components/modbus_controller/binary_sensor/* @martgras
 | 
				
			||||||
esphome/components/modbus_controller/number/* @martgras
 | 
					esphome/components/modbus_controller/number/* @martgras
 | 
				
			||||||
esphome/components/modbus_controller/output/* @martgras
 | 
					esphome/components/modbus_controller/output/* @martgras
 | 
				
			||||||
 | 
					esphome/components/modbus_controller/select/* @martgras @stegm
 | 
				
			||||||
esphome/components/modbus_controller/sensor/* @martgras
 | 
					esphome/components/modbus_controller/sensor/* @martgras
 | 
				
			||||||
esphome/components/modbus_controller/switch/* @martgras
 | 
					esphome/components/modbus_controller/switch/* @martgras
 | 
				
			||||||
esphome/components/modbus_controller/text_sensor/* @martgras
 | 
					esphome/components/modbus_controller/text_sensor/* @martgras
 | 
				
			||||||
 | 
					esphome/components/mopeka_ble/* @spbrogan
 | 
				
			||||||
 | 
					esphome/components/mopeka_pro_check/* @spbrogan
 | 
				
			||||||
 | 
					esphome/components/mpl3115a2/* @kbickar
 | 
				
			||||||
 | 
					esphome/components/mpu6886/* @fabaff
 | 
				
			||||||
esphome/components/network/* @esphome/core
 | 
					esphome/components/network/* @esphome/core
 | 
				
			||||||
esphome/components/nextion/* @senexcrenshaw
 | 
					esphome/components/nextion/* @senexcrenshaw
 | 
				
			||||||
esphome/components/nextion/binary_sensor/* @senexcrenshaw
 | 
					esphome/components/nextion/binary_sensor/* @senexcrenshaw
 | 
				
			||||||
@@ -123,30 +173,47 @@ esphome/components/pn532_i2c/* @OttoWinter @jesserockz
 | 
				
			|||||||
esphome/components/pn532_spi/* @OttoWinter @jesserockz
 | 
					esphome/components/pn532_spi/* @OttoWinter @jesserockz
 | 
				
			||||||
esphome/components/power_supply/* @esphome/core
 | 
					esphome/components/power_supply/* @esphome/core
 | 
				
			||||||
esphome/components/preferences/* @esphome/core
 | 
					esphome/components/preferences/* @esphome/core
 | 
				
			||||||
esphome/components/pulse_meter/* @stevebaxter
 | 
					esphome/components/psram/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/pulse_meter/* @cstaahl @stevebaxter
 | 
				
			||||||
esphome/components/pvvx_mithermometer/* @pasiz
 | 
					esphome/components/pvvx_mithermometer/* @pasiz
 | 
				
			||||||
 | 
					esphome/components/qmp6988/* @andrewpc
 | 
				
			||||||
 | 
					esphome/components/qr_code/* @wjtje
 | 
				
			||||||
 | 
					esphome/components/radon_eye_ble/* @jeffeb3
 | 
				
			||||||
 | 
					esphome/components/radon_eye_rd200/* @jeffeb3
 | 
				
			||||||
esphome/components/rc522/* @glmnet
 | 
					esphome/components/rc522/* @glmnet
 | 
				
			||||||
esphome/components/rc522_i2c/* @glmnet
 | 
					esphome/components/rc522_i2c/* @glmnet
 | 
				
			||||||
esphome/components/rc522_spi/* @glmnet
 | 
					esphome/components/rc522_spi/* @glmnet
 | 
				
			||||||
esphome/components/restart/* @esphome/core
 | 
					esphome/components/restart/* @esphome/core
 | 
				
			||||||
esphome/components/rf_bridge/* @jesserockz
 | 
					esphome/components/rf_bridge/* @jesserockz
 | 
				
			||||||
esphome/components/rgbct/* @jesserockz
 | 
					esphome/components/rgbct/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/rp2040/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/rp2040_pwm/* @jesserockz
 | 
				
			||||||
esphome/components/rtttl/* @glmnet
 | 
					esphome/components/rtttl/* @glmnet
 | 
				
			||||||
esphome/components/safe_mode/* @paulmonigatti
 | 
					esphome/components/safe_mode/* @jsuanet @paulmonigatti
 | 
				
			||||||
esphome/components/scd4x/* @sjtrny
 | 
					esphome/components/scd4x/* @martgras @sjtrny
 | 
				
			||||||
esphome/components/script/* @esphome/core
 | 
					esphome/components/script/* @esphome/core
 | 
				
			||||||
esphome/components/sdm_meter/* @jesserockz @polyfaces
 | 
					esphome/components/sdm_meter/* @jesserockz @polyfaces
 | 
				
			||||||
esphome/components/sdp3x/* @Azimath
 | 
					esphome/components/sdp3x/* @Azimath
 | 
				
			||||||
esphome/components/selec_meter/* @sourabhjaiswal
 | 
					esphome/components/selec_meter/* @sourabhjaiswal
 | 
				
			||||||
esphome/components/select/* @esphome/core
 | 
					esphome/components/select/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/sen5x/* @martgras
 | 
				
			||||||
 | 
					esphome/components/sensirion_common/* @martgras
 | 
				
			||||||
esphome/components/sensor/* @esphome/core
 | 
					esphome/components/sensor/* @esphome/core
 | 
				
			||||||
esphome/components/sgp40/* @SenexCrenshaw
 | 
					esphome/components/sgp40/* @SenexCrenshaw
 | 
				
			||||||
 | 
					esphome/components/sgp4x/* @SenexCrenshaw @martgras
 | 
				
			||||||
 | 
					esphome/components/shelly_dimmer/* @edge90 @rnauber
 | 
				
			||||||
esphome/components/sht4x/* @sjtrny
 | 
					esphome/components/sht4x/* @sjtrny
 | 
				
			||||||
esphome/components/shutdown/* @esphome/core
 | 
					esphome/components/shutdown/* @esphome/core @jsuanet
 | 
				
			||||||
esphome/components/sim800l/* @glmnet
 | 
					esphome/components/sim800l/* @glmnet
 | 
				
			||||||
esphome/components/sm2135/* @BoukeHaarsma23
 | 
					esphome/components/sm2135/* @BoukeHaarsma23
 | 
				
			||||||
 | 
					esphome/components/sml/* @alengwenus
 | 
				
			||||||
 | 
					esphome/components/smt100/* @piechade
 | 
				
			||||||
 | 
					esphome/components/sn74hc165/* @jesserockz
 | 
				
			||||||
esphome/components/socket/* @esphome/core
 | 
					esphome/components/socket/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/sonoff_d1/* @anatoly-savchenkov
 | 
				
			||||||
esphome/components/spi/* @esphome/core
 | 
					esphome/components/spi/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/sprinkler/* @kbx81
 | 
				
			||||||
 | 
					esphome/components/sps30/* @martgras
 | 
				
			||||||
esphome/components/ssd1322_base/* @kbx81
 | 
					esphome/components/ssd1322_base/* @kbx81
 | 
				
			||||||
esphome/components/ssd1322_spi/* @kbx81
 | 
					esphome/components/ssd1322_spi/* @kbx81
 | 
				
			||||||
esphome/components/ssd1325_base/* @kbx81
 | 
					esphome/components/ssd1325_base/* @kbx81
 | 
				
			||||||
@@ -171,21 +238,34 @@ esphome/components/teleinfo/* @0hax
 | 
				
			|||||||
esphome/components/thermostat/* @kbx81
 | 
					esphome/components/thermostat/* @kbx81
 | 
				
			||||||
esphome/components/time/* @OttoWinter
 | 
					esphome/components/time/* @OttoWinter
 | 
				
			||||||
esphome/components/tlc5947/* @rnauber
 | 
					esphome/components/tlc5947/* @rnauber
 | 
				
			||||||
 | 
					esphome/components/tm1621/* @Philippe12
 | 
				
			||||||
esphome/components/tm1637/* @glmnet
 | 
					esphome/components/tm1637/* @glmnet
 | 
				
			||||||
 | 
					esphome/components/tm1638/* @skykingjwc
 | 
				
			||||||
esphome/components/tmp102/* @timsavage
 | 
					esphome/components/tmp102/* @timsavage
 | 
				
			||||||
esphome/components/tmp117/* @Azimath
 | 
					esphome/components/tmp117/* @Azimath
 | 
				
			||||||
esphome/components/tof10120/* @wstrzalka
 | 
					esphome/components/tof10120/* @wstrzalka
 | 
				
			||||||
esphome/components/toshiba/* @kbx81
 | 
					esphome/components/toshiba/* @kbx81
 | 
				
			||||||
 | 
					esphome/components/touchscreen/* @jesserockz
 | 
				
			||||||
esphome/components/tsl2591/* @wjcarpenter
 | 
					esphome/components/tsl2591/* @wjcarpenter
 | 
				
			||||||
esphome/components/tuya/binary_sensor/* @jesserockz
 | 
					esphome/components/tuya/binary_sensor/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/climate/* @jesserockz
 | 
					esphome/components/tuya/climate/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/tuya/number/* @frankiboy1
 | 
				
			||||||
 | 
					esphome/components/tuya/select/* @bearpawmaxim
 | 
				
			||||||
esphome/components/tuya/sensor/* @jesserockz
 | 
					esphome/components/tuya/sensor/* @jesserockz
 | 
				
			||||||
esphome/components/tuya/switch/* @jesserockz
 | 
					esphome/components/tuya/switch/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/tuya/text_sensor/* @dentra
 | 
				
			||||||
esphome/components/uart/* @esphome/core
 | 
					esphome/components/uart/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/ufire_ec/* @pvizeli
 | 
				
			||||||
 | 
					esphome/components/ufire_ise/* @pvizeli
 | 
				
			||||||
esphome/components/ultrasonic/* @OttoWinter
 | 
					esphome/components/ultrasonic/* @OttoWinter
 | 
				
			||||||
esphome/components/version/* @esphome/core
 | 
					esphome/components/version/* @esphome/core
 | 
				
			||||||
 | 
					esphome/components/wake_on_lan/* @willwill2will54
 | 
				
			||||||
esphome/components/web_server_base/* @OttoWinter
 | 
					esphome/components/web_server_base/* @OttoWinter
 | 
				
			||||||
esphome/components/whirlpool/* @glmnet
 | 
					esphome/components/whirlpool/* @glmnet
 | 
				
			||||||
 | 
					esphome/components/whynter/* @aeonsablaze
 | 
				
			||||||
 | 
					esphome/components/wl_134/* @hobbypunk90
 | 
				
			||||||
esphome/components/xiaomi_lywsd03mmc/* @ahpohl
 | 
					esphome/components/xiaomi_lywsd03mmc/* @ahpohl
 | 
				
			||||||
 | 
					esphome/components/xiaomi_mhoc303/* @drug123
 | 
				
			||||||
esphome/components/xiaomi_mhoc401/* @vevsvevs
 | 
					esphome/components/xiaomi_mhoc401/* @vevsvevs
 | 
				
			||||||
esphome/components/xpt2046/* @numo68
 | 
					esphome/components/xiaomi_rtcgq02lm/* @jesserockz
 | 
				
			||||||
 | 
					esphome/components/xpt2046/* @nielsnl68 @numo68
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ For a detailed guide, please see https://esphome.io/guides/contributing.html#con
 | 
				
			|||||||
Things to note when contributing:
 | 
					Things to note when contributing:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 - Please test your changes :)
 | 
					 - Please test your changes :)
 | 
				
			||||||
 - If a new feature is added or an existing user-facing feature is changed, you should also 
 | 
					 - If a new feature is added or an existing user-facing feature is changed, you should also
 | 
				
			||||||
   update the [docs](https://github.com/esphome/esphome-docs). See [contributing to esphome-docs](https://esphome.io/guides/contributing.html#contributing-to-esphomedocs)
 | 
					   update the [docs](https://github.com/esphome/esphome-docs). See [contributing to esphome-docs](https://esphome.io/guides/contributing.html#contributing-to-esphomedocs)
 | 
				
			||||||
   for more information.
 | 
					   for more information.
 | 
				
			||||||
 - Please also update the tests in the `tests/` folder. You can do so by just adding a line in one of the YAML files
 | 
					 - Please also update the tests in the `tests/` folder. You can do so by just adding a line in one of the YAML files
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,4 +4,5 @@ include requirements.txt
 | 
				
			|||||||
include esphome/dashboard/templates/*.html
 | 
					include esphome/dashboard/templates/*.html
 | 
				
			||||||
recursive-include esphome/dashboard/static *.ico *.js *.css *.woff* LICENSE
 | 
					recursive-include esphome/dashboard/static *.ico *.js *.css *.woff* LICENSE
 | 
				
			||||||
recursive-include esphome *.cpp *.h *.tcc
 | 
					recursive-include esphome *.cpp *.h *.tcc
 | 
				
			||||||
 | 
					recursive-include esphome *.py.script
 | 
				
			||||||
recursive-include esphome LICENSE.txt
 | 
					recursive-include esphome LICENSE.txt
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,29 +5,26 @@
 | 
				
			|||||||
# One of "docker", "hassio"
 | 
					# One of "docker", "hassio"
 | 
				
			||||||
ARG BASEIMGTYPE=docker
 | 
					ARG BASEIMGTYPE=docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/amd64:5.1.1 AS base-hassio-amd64
 | 
					# https://github.com/hassio-addons/addon-debian-base/releases
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/aarch64:5.1.1 AS base-hassio-arm64
 | 
					FROM ghcr.io/hassio-addons/debian-base:6.1.3 AS base-hassio
 | 
				
			||||||
FROM ghcr.io/hassio-addons/debian-base/armv7:5.1.1 AS base-hassio-armv7
 | 
					# https://hub.docker.com/_/debian?tab=tags&page=1&name=bullseye
 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-amd64
 | 
					FROM debian:bullseye-20221024-slim AS base-docker
 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-arm64
 | 
					 | 
				
			||||||
FROM debian:bullseye-20211011-slim AS base-docker-armv7
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Use TARGETARCH/TARGETVARIANT defined by docker
 | 
					FROM base-${BASEIMGTYPE} AS base
 | 
				
			||||||
# https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
 | 
					 | 
				
			||||||
FROM base-${BASEIMGTYPE}-${TARGETARCH}${TARGETVARIANT} AS base
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
RUN \
 | 
					RUN \
 | 
				
			||||||
    apt-get update \
 | 
					    apt-get update \
 | 
				
			||||||
    # Use pinned versions so that we get updates with build caching
 | 
					    # Use pinned versions so that we get updates with build caching
 | 
				
			||||||
    && apt-get install -y --no-install-recommends \
 | 
					    && apt-get install -y --no-install-recommends \
 | 
				
			||||||
        python3=3.9.2-3 \
 | 
					        python3=3.9.2-3 \
 | 
				
			||||||
        python3-pip=20.3.4-4 \
 | 
					        python3-pip=20.3.4-4+deb11u1 \
 | 
				
			||||||
        python3-setuptools=52.0.0-4 \
 | 
					        python3-setuptools=52.0.0-4 \
 | 
				
			||||||
        python3-pil=8.1.2+dfsg-0.3 \
 | 
					        python3-pil=8.1.2+dfsg-0.3+deb11u1 \
 | 
				
			||||||
        python3-cryptography=3.3.2-1 \
 | 
					        python3-cryptography=3.3.2-1 \
 | 
				
			||||||
        iputils-ping=3:20210202-1 \
 | 
					        iputils-ping=3:20210202-1 \
 | 
				
			||||||
        git=1:2.30.2-1 \
 | 
					        git=1:2.30.2-1 \
 | 
				
			||||||
        curl=7.74.0-1.3+b1 \
 | 
					        curl=7.74.0-1.3+deb11u3 \
 | 
				
			||||||
 | 
					        openssh-client=1:8.4p1-5+deb11u1 \
 | 
				
			||||||
    && rm -rf \
 | 
					    && rm -rf \
 | 
				
			||||||
        /tmp/* \
 | 
					        /tmp/* \
 | 
				
			||||||
        /var/{cache,log}/* \
 | 
					        /var/{cache,log}/* \
 | 
				
			||||||
@@ -42,29 +39,27 @@ ENV \
 | 
				
			|||||||
RUN \
 | 
					RUN \
 | 
				
			||||||
    # Ubuntu python3-pip is missing wheel
 | 
					    # Ubuntu python3-pip is missing wheel
 | 
				
			||||||
    pip3 install --no-cache-dir \
 | 
					    pip3 install --no-cache-dir \
 | 
				
			||||||
        wheel==0.36.2 \
 | 
					        wheel==0.37.1 \
 | 
				
			||||||
        platformio==5.2.2 \
 | 
					        platformio==6.1.5 \
 | 
				
			||||||
    # Change some platformio settings
 | 
					    # Change some platformio settings
 | 
				
			||||||
    && platformio settings set enable_telemetry No \
 | 
					    && platformio settings set enable_telemetry No \
 | 
				
			||||||
    && platformio settings set check_libraries_interval 1000000 \
 | 
					 | 
				
			||||||
    && platformio settings set check_platformio_interval 1000000 \
 | 
					    && platformio settings set check_platformio_interval 1000000 \
 | 
				
			||||||
    && platformio settings set check_platforms_interval 1000000 \
 | 
					 | 
				
			||||||
    && mkdir -p /piolibs
 | 
					    && mkdir -p /piolibs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# ======================= docker-type image =======================
 | 
					 | 
				
			||||||
FROM base AS docker
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# First install requirements to leverage caching when requirements don't change
 | 
					# First install requirements to leverage caching when requirements don't change
 | 
				
			||||||
COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
 | 
					COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
 | 
				
			||||||
RUN \
 | 
					RUN \
 | 
				
			||||||
    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
 | 
					    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
 | 
				
			||||||
    && /platformio_install_deps.py /platformio.ini
 | 
					    && /platformio_install_deps.py /platformio.ini
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# ======================= docker-type image =======================
 | 
				
			||||||
 | 
					FROM base AS docker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Copy esphome and install
 | 
					# Copy esphome and install
 | 
				
			||||||
COPY . /esphome
 | 
					COPY . /esphome
 | 
				
			||||||
RUN pip3 install --no-cache-dir -e /esphome
 | 
					RUN pip3 install --no-cache-dir --no-use-pep517 -e /esphome
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Settings for dashboard
 | 
					# Settings for dashboard
 | 
				
			||||||
ENV USERNAME="" PASSWORD=""
 | 
					ENV USERNAME="" PASSWORD=""
 | 
				
			||||||
@@ -93,7 +88,7 @@ RUN \
 | 
				
			|||||||
    apt-get update \
 | 
					    apt-get update \
 | 
				
			||||||
    # Use pinned versions so that we get updates with build caching
 | 
					    # Use pinned versions so that we get updates with build caching
 | 
				
			||||||
    && apt-get install -y --no-install-recommends \
 | 
					    && apt-get install -y --no-install-recommends \
 | 
				
			||||||
        nginx=1.18.0-6.1 \
 | 
					        nginx-light=1.18.0-6.1+deb11u3 \
 | 
				
			||||||
    && rm -rf \
 | 
					    && rm -rf \
 | 
				
			||||||
        /tmp/* \
 | 
					        /tmp/* \
 | 
				
			||||||
        /var/{cache,log}/* \
 | 
					        /var/{cache,log}/* \
 | 
				
			||||||
@@ -102,17 +97,11 @@ RUN \
 | 
				
			|||||||
ARG BUILD_VERSION=dev
 | 
					ARG BUILD_VERSION=dev
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Copy root filesystem
 | 
					# Copy root filesystem
 | 
				
			||||||
COPY docker/hassio-rootfs/ /
 | 
					COPY docker/ha-addon-rootfs/ /
 | 
				
			||||||
 | 
					 | 
				
			||||||
# First install requirements to leverage caching when requirements don't change
 | 
					 | 
				
			||||||
COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
 | 
					 | 
				
			||||||
RUN \
 | 
					 | 
				
			||||||
    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
 | 
					 | 
				
			||||||
    && /platformio_install_deps.py /platformio.ini
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Copy esphome and install
 | 
					# Copy esphome and install
 | 
				
			||||||
COPY . /esphome
 | 
					COPY . /esphome
 | 
				
			||||||
RUN pip3 install --no-cache-dir -e /esphome
 | 
					RUN pip3 install --no-cache-dir --no-use-pep517 -e /esphome
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Labels
 | 
					# Labels
 | 
				
			||||||
LABEL \
 | 
					LABEL \
 | 
				
			||||||
@@ -139,7 +128,7 @@ RUN \
 | 
				
			|||||||
        clang-tidy-11=1:11.0.1-2 \
 | 
					        clang-tidy-11=1:11.0.1-2 \
 | 
				
			||||||
        patch=2.7.6-7 \
 | 
					        patch=2.7.6-7 \
 | 
				
			||||||
        software-properties-common=0.96.20.2-2.1 \
 | 
					        software-properties-common=0.96.20.2-2.1 \
 | 
				
			||||||
        nano=5.4-2 \
 | 
					        nano=5.4-2+deb11u1 \
 | 
				
			||||||
        build-essential=12.9 \
 | 
					        build-essential=12.9 \
 | 
				
			||||||
        python3-dev=3.9.2-3 \
 | 
					        python3-dev=3.9.2-3 \
 | 
				
			||||||
    && rm -rf \
 | 
					    && rm -rf \
 | 
				
			||||||
@@ -147,10 +136,8 @@ RUN \
 | 
				
			|||||||
        /var/{cache,log}/* \
 | 
					        /var/{cache,log}/* \
 | 
				
			||||||
        /var/lib/apt/lists/*
 | 
					        /var/lib/apt/lists/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COPY requirements.txt requirements_optional.txt docker/platformio_install_deps.py platformio.ini /
 | 
					COPY requirements_test.txt /
 | 
				
			||||||
RUN \
 | 
					RUN pip3 install --no-cache-dir -r /requirements_test.txt
 | 
				
			||||||
    pip3 install --no-cache-dir -r /requirements.txt -r /requirements_optional.txt \
 | 
					 | 
				
			||||||
    && /platformio_install_deps.py /platformio.ini
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
VOLUME ["/esphome"]
 | 
					VOLUME ["/esphome"]
 | 
				
			||||||
WORKDIR /esphome
 | 
					WORKDIR /esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,6 +32,7 @@ parser.add_argument("--dry-run", action="store_true", help="Don't run any comman
 | 
				
			|||||||
subparsers = parser.add_subparsers(help="Action to perform", dest="command", required=True)
 | 
					subparsers = parser.add_subparsers(help="Action to perform", dest="command", required=True)
 | 
				
			||||||
build_parser = subparsers.add_parser("build", help="Build the image")
 | 
					build_parser = subparsers.add_parser("build", help="Build the image")
 | 
				
			||||||
build_parser.add_argument("--push", help="Also push the images", action="store_true")
 | 
					build_parser.add_argument("--push", help="Also push the images", action="store_true")
 | 
				
			||||||
 | 
					build_parser.add_argument("--load", help="Load the docker image locally", action="store_true")
 | 
				
			||||||
manifest_parser = subparsers.add_parser("manifest", help="Create a manifest from already pushed images")
 | 
					manifest_parser = subparsers.add_parser("manifest", help="Create a manifest from already pushed images")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,10 +88,12 @@ def main():
 | 
				
			|||||||
                sys.exit(1)
 | 
					                sys.exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # detect channel from tag
 | 
					    # detect channel from tag
 | 
				
			||||||
    match = re.match(r'^\d+\.\d+(?:\.\d+)?(b\d+)?$', args.tag)
 | 
					    match = re.match(r"^(\d+\.\d+)(?:\.\d+)?(b\d+)?$", args.tag)
 | 
				
			||||||
 | 
					    major_minor_version = None
 | 
				
			||||||
    if match is None:
 | 
					    if match is None:
 | 
				
			||||||
        channel = CHANNEL_DEV
 | 
					        channel = CHANNEL_DEV
 | 
				
			||||||
    elif match.group(1) is None:
 | 
					    elif match.group(2) is None:
 | 
				
			||||||
 | 
					        major_minor_version = match.group(1)
 | 
				
			||||||
        channel = CHANNEL_RELEASE
 | 
					        channel = CHANNEL_RELEASE
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        channel = CHANNEL_BETA
 | 
					        channel = CHANNEL_BETA
 | 
				
			||||||
@@ -105,6 +108,11 @@ def main():
 | 
				
			|||||||
        tags_to_push.append("beta")
 | 
					        tags_to_push.append("beta")
 | 
				
			||||||
        tags_to_push.append("latest")
 | 
					        tags_to_push.append("latest")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Compatibility with HA tags
 | 
				
			||||||
 | 
					        if major_minor_version:
 | 
				
			||||||
 | 
					            tags_to_push.append("stable")
 | 
				
			||||||
 | 
					            tags_to_push.append(major_minor_version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if args.command == "build":
 | 
					    if args.command == "build":
 | 
				
			||||||
        # 1. pull cache image
 | 
					        # 1. pull cache image
 | 
				
			||||||
        params = DockerParams.for_type_arch(args.build_type, args.arch)
 | 
					        params = DockerParams.for_type_arch(args.build_type, args.arch)
 | 
				
			||||||
@@ -132,6 +140,8 @@ def main():
 | 
				
			|||||||
            cmd += ["--tag", img]
 | 
					            cmd += ["--tag", img]
 | 
				
			||||||
        if args.push:
 | 
					        if args.push:
 | 
				
			||||||
            cmd += ["--push", "--cache-to", f"type=registry,ref={cache_img},mode=max"]
 | 
					            cmd += ["--push", "--cache-to", f"type=registry,ref={cache_img},mode=max"]
 | 
				
			||||||
 | 
					        if args.load:
 | 
				
			||||||
 | 
					            cmd += ["--load"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        run_command(*cmd, ".")
 | 
					        run_command(*cmd, ".")
 | 
				
			||||||
    elif args.command == "manifest":
 | 
					    elif args.command == "manifest":
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,12 +7,12 @@
 | 
				
			|||||||
# Check SSL requirements, if enabled
 | 
					# Check SSL requirements, if enabled
 | 
				
			||||||
if bashio::config.true 'ssl'; then
 | 
					if bashio::config.true 'ssl'; then
 | 
				
			||||||
    if ! bashio::config.has_value 'certfile'; then
 | 
					    if ! bashio::config.has_value 'certfile'; then
 | 
				
			||||||
        bashio::fatal 'SSL is enabled, but no certfile was specified.'
 | 
					        bashio::log.fatal 'SSL is enabled, but no certfile was specified.'
 | 
				
			||||||
        bashio::exit.nok
 | 
					        bashio::exit.nok
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ! bashio::config.has_value 'keyfile'; then
 | 
					    if ! bashio::config.has_value 'keyfile'; then
 | 
				
			||||||
        bashio::fatal 'SSL is enabled, but no keyfile was specified'
 | 
					        bashio::log.fatal 'SSL is enabled, but no keyfile was specified'
 | 
				
			||||||
        bashio::exit.nok
 | 
					        bashio::exit.nok
 | 
				
			||||||
    fi
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										0
									
								
								docker/hassio-rootfs/etc/cont-init.d/30-dirs.sh → docker/ha-addon-rootfs/etc/cont-init.d/30-dirs.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										0
									
								
								docker/hassio-rootfs/etc/cont-init.d/30-dirs.sh → docker/ha-addon-rootfs/etc/cont-init.d/30-dirs.sh
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							@@ -10,7 +10,7 @@ server {
 | 
				
			|||||||
    ssl_certificate_key /ssl/%%keyfile%%;
 | 
					    ssl_certificate_key /ssl/%%keyfile%%;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Clear Hass.io Ingress header
 | 
					    # Clear Hass.io Ingress header
 | 
				
			||||||
    proxy_set_header X-Hassio-Ingress "";
 | 
					    proxy_set_header X-HA-Ingress "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Redirect http requests to https on the same port.
 | 
					    # Redirect http requests to https on the same port.
 | 
				
			||||||
    # https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
 | 
					    # https://rageagainstshell.com/2016/11/redirect-http-to-https-on-the-same-port-in-nginx/
 | 
				
			||||||
@@ -4,7 +4,7 @@ server {
 | 
				
			|||||||
    include /etc/nginx/includes/server_params.conf;
 | 
					    include /etc/nginx/includes/server_params.conf;
 | 
				
			||||||
    include /etc/nginx/includes/proxy_params.conf;
 | 
					    include /etc/nginx/includes/proxy_params.conf;
 | 
				
			||||||
    # Clear Hass.io Ingress header
 | 
					    # Clear Hass.io Ingress header
 | 
				
			||||||
    proxy_set_header X-Hassio-Ingress "";
 | 
					    proxy_set_header X-HA-Ingress "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    location / {
 | 
					    location / {
 | 
				
			||||||
        proxy_pass http://esphome;
 | 
					        proxy_pass http://esphome;
 | 
				
			||||||
@@ -3,8 +3,8 @@ server {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    include /etc/nginx/includes/server_params.conf;
 | 
					    include /etc/nginx/includes/server_params.conf;
 | 
				
			||||||
    include /etc/nginx/includes/proxy_params.conf;
 | 
					    include /etc/nginx/includes/proxy_params.conf;
 | 
				
			||||||
    # Set Hass.io Ingress header
 | 
					    # Set Home Assistant Ingress header
 | 
				
			||||||
    proxy_set_header X-Hassio-Ingress "YES";
 | 
					    proxy_set_header X-HA-Ingress "YES";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    location / {
 | 
					    location / {
 | 
				
			||||||
        # Only allow from Hass.io supervisor
 | 
					        # Only allow from Hass.io supervisor
 | 
				
			||||||
							
								
								
									
										15
									
								
								docker/ha-addon-rootfs/etc/services.d/esphome/finish
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								docker/ha-addon-rootfs/etc/services.d/esphome/finish
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/execlineb -S0
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					# Community Hass.io Add-ons: ESPHome
 | 
				
			||||||
 | 
					# Take down the S6 supervision tree when ESPHome fails
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare APP_EXIT_CODE=${1}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then
 | 
				
			||||||
 | 
					  bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}"
 | 
				
			||||||
 | 
					  echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode
 | 
				
			||||||
 | 
					  exec /run/s6/basedir/bin/halt
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bashio::log.info "Service restart after closing"
 | 
				
			||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
# Runs the ESPHome dashboard
 | 
					# Runs the ESPHome dashboard
 | 
				
			||||||
# ==============================================================================
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export ESPHOME_IS_HASSIO=true
 | 
					export ESPHOME_IS_HA_ADDON=true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if bashio::config.true 'leave_front_door_open'; then
 | 
					if bashio::config.true 'leave_front_door_open'; then
 | 
				
			||||||
    export DISABLE_HA_AUTHENTICATION=true
 | 
					    export DISABLE_HA_AUTHENTICATION=true
 | 
				
			||||||
@@ -22,6 +22,14 @@ if bashio::config.has_value 'relative_url'; then
 | 
				
			|||||||
    export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
 | 
					    export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
 | 
				
			||||||
fi
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if bashio::config.has_value 'default_compile_process_limit'; then
 | 
				
			||||||
 | 
					    export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=$(bashio::config 'default_compile_process_limit')
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					    if grep -q 'Raspberry Pi 3' /proc/cpuinfo; then
 | 
				
			||||||
 | 
					        export ESPHOME_DEFAULT_COMPILE_PROCESS_LIMIT=1;
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pio_cache_base=/data/cache/platformio
 | 
					pio_cache_base=/data/cache/platformio
 | 
				
			||||||
# we can't set core_dir, because the settings file is stored in `core_dir/appstate.json`
 | 
					# we can't set core_dir, because the settings file is stored in `core_dir/appstate.json`
 | 
				
			||||||
# setting `core_dir` would therefore prevent pio from accessing
 | 
					# setting `core_dir` would therefore prevent pio from accessing
 | 
				
			||||||
@@ -32,4 +40,4 @@ export PLATFORMIO_CACHE_DIR="${pio_cache_base}/cache"
 | 
				
			|||||||
export PLATFORMIO_GLOBALLIB_DIR=/piolibs
 | 
					export PLATFORMIO_GLOBALLIB_DIR=/piolibs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bashio::log.info "Starting ESPHome dashboard..."
 | 
					bashio::log.info "Starting ESPHome dashboard..."
 | 
				
			||||||
exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --hassio
 | 
					exec esphome dashboard /config/esphome --socket /var/run/esphome.sock --ha-addon
 | 
				
			||||||
							
								
								
									
										15
									
								
								docker/ha-addon-rootfs/etc/services.d/nginx/finish
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										15
									
								
								docker/ha-addon-rootfs/etc/services.d/nginx/finish
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/execlineb -S0
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					# Community Hass.io Add-ons: ESPHome
 | 
				
			||||||
 | 
					# Take down the S6 supervision tree when NGINX fails
 | 
				
			||||||
 | 
					# ==============================================================================
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					declare APP_EXIT_CODE=${1}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [[ "${APP_EXIT_CODE}" -ne 0 ]] && [[ "${APP_EXIT_CODE}" -ne 256 ]]; then
 | 
				
			||||||
 | 
					  bashio::log.warning "Halt add-on with exit code ${APP_EXIT_CODE}"
 | 
				
			||||||
 | 
					  echo "${APP_EXIT_CODE}" > /run/s6-linux-init-container-results/exitcode
 | 
				
			||||||
 | 
					  exec /run/s6/basedir/bin/halt
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bashio::log.info "Service restart after closing"
 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
#!/usr/bin/execlineb -S0
 | 
					 | 
				
			||||||
# ==============================================================================
 | 
					 | 
				
			||||||
# Community Hass.io Add-ons: ESPHome
 | 
					 | 
				
			||||||
# Take down the S6 supervision tree when ESPHome fails
 | 
					 | 
				
			||||||
# ==============================================================================
 | 
					 | 
				
			||||||
if -n { s6-test $# -ne 0 }
 | 
					 | 
				
			||||||
if -n { s6-test ${1} -eq 256 }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
s6-svscanctl -t /var/run/s6/services
 | 
					 | 
				
			||||||
@@ -1,9 +0,0 @@
 | 
				
			|||||||
#!/usr/bin/execlineb -S0
 | 
					 | 
				
			||||||
# ==============================================================================
 | 
					 | 
				
			||||||
# Community Hass.io Add-ons: ESPHome
 | 
					 | 
				
			||||||
# Take down the S6 supervision tree when NGINX fails
 | 
					 | 
				
			||||||
# ==============================================================================
 | 
					 | 
				
			||||||
if -n { s6-test $# -ne 0 }
 | 
					 | 
				
			||||||
if -n { s6-test ${1} -eq 256 }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
s6-svscanctl -t /var/run/s6/services
 | 
					 | 
				
			||||||
@@ -2,22 +2,31 @@ import argparse
 | 
				
			|||||||
import functools
 | 
					import functools
 | 
				
			||||||
import logging
 | 
					import logging
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from esphome import const, writer, yaml_util
 | 
					from esphome import const, writer, yaml_util
 | 
				
			||||||
import esphome.codegen as cg
 | 
					import esphome.codegen as cg
 | 
				
			||||||
from esphome.config import iter_components, read_config, strip_default_ids
 | 
					from esphome.config import iter_components, read_config, strip_default_ids
 | 
				
			||||||
from esphome.const import (
 | 
					from esphome.const import (
 | 
				
			||||||
 | 
					    ALLOWED_NAME_CHARS,
 | 
				
			||||||
    CONF_BAUD_RATE,
 | 
					    CONF_BAUD_RATE,
 | 
				
			||||||
    CONF_BROKER,
 | 
					    CONF_BROKER,
 | 
				
			||||||
    CONF_DEASSERT_RTS_DTR,
 | 
					    CONF_DEASSERT_RTS_DTR,
 | 
				
			||||||
    CONF_LOGGER,
 | 
					    CONF_LOGGER,
 | 
				
			||||||
 | 
					    CONF_NAME,
 | 
				
			||||||
    CONF_OTA,
 | 
					    CONF_OTA,
 | 
				
			||||||
    CONF_PASSWORD,
 | 
					    CONF_PASSWORD,
 | 
				
			||||||
    CONF_PORT,
 | 
					    CONF_PORT,
 | 
				
			||||||
    CONF_ESPHOME,
 | 
					    CONF_ESPHOME,
 | 
				
			||||||
    CONF_PLATFORMIO_OPTIONS,
 | 
					    CONF_PLATFORMIO_OPTIONS,
 | 
				
			||||||
 | 
					    CONF_SUBSTITUTIONS,
 | 
				
			||||||
 | 
					    PLATFORM_ESP32,
 | 
				
			||||||
 | 
					    PLATFORM_ESP8266,
 | 
				
			||||||
 | 
					    PLATFORM_RP2040,
 | 
				
			||||||
 | 
					    SECRETS_FILES,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from esphome.core import CORE, EsphomeError, coroutine
 | 
					from esphome.core import CORE, EsphomeError, coroutine
 | 
				
			||||||
from esphome.helpers import indent
 | 
					from esphome.helpers import indent
 | 
				
			||||||
@@ -96,11 +105,11 @@ def run_miniterm(config, port):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if CONF_LOGGER not in config:
 | 
					    if CONF_LOGGER not in config:
 | 
				
			||||||
        _LOGGER.info("Logger is not enabled. Not starting UART logs.")
 | 
					        _LOGGER.info("Logger is not enabled. Not starting UART logs.")
 | 
				
			||||||
        return
 | 
					        return 1
 | 
				
			||||||
    baud_rate = config["logger"][CONF_BAUD_RATE]
 | 
					    baud_rate = config["logger"][CONF_BAUD_RATE]
 | 
				
			||||||
    if baud_rate == 0:
 | 
					    if baud_rate == 0:
 | 
				
			||||||
        _LOGGER.info("UART logging is disabled (baud_rate=0). Not starting UART logs.")
 | 
					        _LOGGER.info("UART logging is disabled (baud_rate=0). Not starting UART logs.")
 | 
				
			||||||
        return
 | 
					        return 1
 | 
				
			||||||
    _LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate)
 | 
					    _LOGGER.info("Starting log output from %s with baud rate %s", port, baud_rate)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    backtrace_state = False
 | 
					    backtrace_state = False
 | 
				
			||||||
@@ -114,25 +123,34 @@ def run_miniterm(config, port):
 | 
				
			|||||||
        ser.dtr = False
 | 
					        ser.dtr = False
 | 
				
			||||||
        ser.rts = False
 | 
					        ser.rts = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with ser:
 | 
					    tries = 0
 | 
				
			||||||
        while True:
 | 
					    while tries < 5:
 | 
				
			||||||
            try:
 | 
					        try:
 | 
				
			||||||
                raw = ser.readline()
 | 
					            with ser:
 | 
				
			||||||
            except serial.SerialException:
 | 
					                while True:
 | 
				
			||||||
                _LOGGER.error("Serial port closed!")
 | 
					                    try:
 | 
				
			||||||
                return
 | 
					                        raw = ser.readline()
 | 
				
			||||||
            line = (
 | 
					                    except serial.SerialException:
 | 
				
			||||||
                raw.replace(b"\r", b"")
 | 
					                        _LOGGER.error("Serial port closed!")
 | 
				
			||||||
                .replace(b"\n", b"")
 | 
					                        return 0
 | 
				
			||||||
                .decode("utf8", "backslashreplace")
 | 
					                    line = (
 | 
				
			||||||
            )
 | 
					                        raw.replace(b"\r", b"")
 | 
				
			||||||
            time = datetime.now().time().strftime("[%H:%M:%S]")
 | 
					                        .replace(b"\n", b"")
 | 
				
			||||||
            message = time + line
 | 
					                        .decode("utf8", "backslashreplace")
 | 
				
			||||||
            safe_print(message)
 | 
					                    )
 | 
				
			||||||
 | 
					                    time_str = datetime.now().time().strftime("[%H:%M:%S]")
 | 
				
			||||||
 | 
					                    message = time_str + line
 | 
				
			||||||
 | 
					                    safe_print(message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            backtrace_state = platformio_api.process_stacktrace(
 | 
					                    backtrace_state = platformio_api.process_stacktrace(
 | 
				
			||||||
                config, line, backtrace_state=backtrace_state
 | 
					                        config, line, backtrace_state=backtrace_state
 | 
				
			||||||
            )
 | 
					                    )
 | 
				
			||||||
 | 
					        except serial.SerialException:
 | 
				
			||||||
 | 
					            tries += 1
 | 
				
			||||||
 | 
					            time.sleep(1)
 | 
				
			||||||
 | 
					    if tries >= 5:
 | 
				
			||||||
 | 
					        _LOGGER.error("Could not connect to serial port %s", port)
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def wrap_to_code(name, comp):
 | 
					def wrap_to_code(name, comp):
 | 
				
			||||||
@@ -144,6 +162,8 @@ def wrap_to_code(name, comp):
 | 
				
			|||||||
        if comp.config_schema is not None:
 | 
					        if comp.config_schema is not None:
 | 
				
			||||||
            conf_str = yaml_util.dump(conf)
 | 
					            conf_str = yaml_util.dump(conf)
 | 
				
			||||||
            conf_str = conf_str.replace("//", "")
 | 
					            conf_str = conf_str.replace("//", "")
 | 
				
			||||||
 | 
					            # remove tailing \ to avoid multi-line comment warning
 | 
				
			||||||
 | 
					            conf_str = conf_str.replace("\\\n", "\n")
 | 
				
			||||||
            cg.add(cg.LineComment(indent(conf_str)))
 | 
					            cg.add(cg.LineComment(indent(conf_str)))
 | 
				
			||||||
        await coro(conf)
 | 
					        await coro(conf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -200,8 +220,7 @@ def upload_using_esptool(config, port):
 | 
				
			|||||||
        firmware_offset = "0x10000" if CORE.is_esp32 else "0x0"
 | 
					        firmware_offset = "0x10000" if CORE.is_esp32 else "0x0"
 | 
				
			||||||
        flash_images = [
 | 
					        flash_images = [
 | 
				
			||||||
            platformio_api.FlashImage(
 | 
					            platformio_api.FlashImage(
 | 
				
			||||||
                path=idedata.firmware_bin_path,
 | 
					                path=idedata.firmware_bin_path, offset=firmware_offset
 | 
				
			||||||
                offset=firmware_offset,
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            *idedata.extra_flash_images,
 | 
					            *idedata.extra_flash_images,
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
@@ -235,8 +254,7 @@ def upload_using_esptool(config, port):
 | 
				
			|||||||
        if os.environ.get("ESPHOME_USE_SUBPROCESS") is None:
 | 
					        if os.environ.get("ESPHOME_USE_SUBPROCESS") is None:
 | 
				
			||||||
            import esptool
 | 
					            import esptool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # pylint: disable=protected-access
 | 
					            return run_external_command(esptool.main, *cmd)  # pylint: disable=no-member
 | 
				
			||||||
            return run_external_command(esptool._main, *cmd)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return run_external_process(*cmd)
 | 
					        return run_external_process(*cmd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -252,9 +270,21 @@ def upload_using_esptool(config, port):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def upload_program(config, args, host):
 | 
					def upload_program(config, args, host):
 | 
				
			||||||
    # if upload is to a serial port use platformio, otherwise assume ota
 | 
					 | 
				
			||||||
    if get_port_type(host) == "SERIAL":
 | 
					    if get_port_type(host) == "SERIAL":
 | 
				
			||||||
        return upload_using_esptool(config, host)
 | 
					        if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
 | 
				
			||||||
 | 
					            return upload_using_esptool(config, host)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if CORE.target_platform in (PLATFORM_RP2040):
 | 
				
			||||||
 | 
					            from esphome import platformio_api
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            upload_args = ["-t", "upload"]
 | 
				
			||||||
 | 
					            if args.device is not None:
 | 
				
			||||||
 | 
					                upload_args += ["--upload-port", args.device]
 | 
				
			||||||
 | 
					            return platformio_api.run_platformio_cli_run(
 | 
				
			||||||
 | 
					                config, CORE.verbose, *upload_args
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return 1  # Unknown target platform
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    from esphome import espota2
 | 
					    from esphome import espota2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -267,6 +297,8 @@ def upload_program(config, args, host):
 | 
				
			|||||||
    ota_conf = config[CONF_OTA]
 | 
					    ota_conf = config[CONF_OTA]
 | 
				
			||||||
    remote_port = ota_conf[CONF_PORT]
 | 
					    remote_port = ota_conf[CONF_PORT]
 | 
				
			||||||
    password = ota_conf.get(CONF_PASSWORD, "")
 | 
					    password = ota_conf.get(CONF_PASSWORD, "")
 | 
				
			||||||
 | 
					    if getattr(args, "file", None) is not None:
 | 
				
			||||||
 | 
					        return espota2.run_ota(host, remote_port, password, args.file)
 | 
				
			||||||
    return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
 | 
					    return espota2.run_ota(host, remote_port, password, CORE.firmware_bin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -274,8 +306,7 @@ def show_logs(config, args, port):
 | 
				
			|||||||
    if "logger" not in config:
 | 
					    if "logger" not in config:
 | 
				
			||||||
        raise EsphomeError("Logger is not configured!")
 | 
					        raise EsphomeError("Logger is not configured!")
 | 
				
			||||||
    if get_port_type(port) == "SERIAL":
 | 
					    if get_port_type(port) == "SERIAL":
 | 
				
			||||||
        run_miniterm(config, port)
 | 
					        return run_miniterm(config, port)
 | 
				
			||||||
        return 0
 | 
					 | 
				
			||||||
    if get_port_type(port) == "NETWORK" and "api" in config:
 | 
					    if get_port_type(port) == "NETWORK" and "api" in config:
 | 
				
			||||||
        from esphome.components.api.client import run_logs
 | 
					        from esphome.components.api.client import run_logs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -479,6 +510,98 @@ def command_idedata(args, config):
 | 
				
			|||||||
    return 0
 | 
					    return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def command_rename(args, config):
 | 
				
			||||||
 | 
					    for c in args.name:
 | 
				
			||||||
 | 
					        if c not in ALLOWED_NAME_CHARS:
 | 
				
			||||||
 | 
					            print(
 | 
				
			||||||
 | 
					                color(
 | 
				
			||||||
 | 
					                    Fore.BOLD_RED,
 | 
				
			||||||
 | 
					                    f"'{c}' is an invalid character for names. Valid characters are: "
 | 
				
			||||||
 | 
					                    f"{ALLOWED_NAME_CHARS} (lowercase, no spaces)",
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					    # Load existing yaml file
 | 
				
			||||||
 | 
					    with open(CORE.config_path, mode="r+", encoding="utf-8") as raw_file:
 | 
				
			||||||
 | 
					        raw_contents = raw_file.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    yaml = yaml_util.load_yaml(CORE.config_path)
 | 
				
			||||||
 | 
					    if CONF_ESPHOME not in yaml or CONF_NAME not in yaml[CONF_ESPHOME]:
 | 
				
			||||||
 | 
					        print(
 | 
				
			||||||
 | 
					            color(Fore.BOLD_RED, "Complex YAML files cannot be automatically renamed.")
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					    old_name = yaml[CONF_ESPHOME][CONF_NAME]
 | 
				
			||||||
 | 
					    match = re.match(r"^\$\{?([a-zA-Z0-9_]+)\}?$", old_name)
 | 
				
			||||||
 | 
					    if match is None:
 | 
				
			||||||
 | 
					        new_raw = re.sub(
 | 
				
			||||||
 | 
					            rf"name:\s+[\"']?{old_name}[\"']?",
 | 
				
			||||||
 | 
					            f'name: "{args.name}"',
 | 
				
			||||||
 | 
					            raw_contents,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        old_name = yaml[CONF_SUBSTITUTIONS][match.group(1)]
 | 
				
			||||||
 | 
					        if (
 | 
				
			||||||
 | 
					            len(
 | 
				
			||||||
 | 
					                re.findall(
 | 
				
			||||||
 | 
					                    rf"^\s+{match.group(1)}:\s+[\"']?{old_name}[\"']?",
 | 
				
			||||||
 | 
					                    raw_contents,
 | 
				
			||||||
 | 
					                    flags=re.MULTILINE,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            > 1
 | 
				
			||||||
 | 
					        ):
 | 
				
			||||||
 | 
					            print(color(Fore.BOLD_RED, "Too many matches in YAML to safely rename"))
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        new_raw = re.sub(
 | 
				
			||||||
 | 
					            rf"^(\s+{match.group(1)}):\s+[\"']?{old_name}[\"']?",
 | 
				
			||||||
 | 
					            f'\\1: "{args.name}"',
 | 
				
			||||||
 | 
					            raw_contents,
 | 
				
			||||||
 | 
					            flags=re.MULTILINE,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    new_path = os.path.join(CORE.config_dir, args.name + ".yaml")
 | 
				
			||||||
 | 
					    print(
 | 
				
			||||||
 | 
					        f"Updating {color(Fore.CYAN, CORE.config_path)} to {color(Fore.CYAN, new_path)}"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    print()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    with open(new_path, mode="w", encoding="utf-8") as new_file:
 | 
				
			||||||
 | 
					        new_file.write(new_raw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rc = run_external_process("esphome", "config", new_path)
 | 
				
			||||||
 | 
					    if rc != 0:
 | 
				
			||||||
 | 
					        print(color(Fore.BOLD_RED, "Rename failed. Reverting changes."))
 | 
				
			||||||
 | 
					        os.remove(new_path)
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    cli_args = [
 | 
				
			||||||
 | 
					        "run",
 | 
				
			||||||
 | 
					        new_path,
 | 
				
			||||||
 | 
					        "--no-logs",
 | 
				
			||||||
 | 
					        "--device",
 | 
				
			||||||
 | 
					        CORE.address,
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if args.dashboard:
 | 
				
			||||||
 | 
					        cli_args.insert(0, "--dashboard")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        rc = run_external_process("esphome", *cli_args)
 | 
				
			||||||
 | 
					    except KeyboardInterrupt:
 | 
				
			||||||
 | 
					        rc = 1
 | 
				
			||||||
 | 
					    if rc != 0:
 | 
				
			||||||
 | 
					        os.remove(new_path)
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    os.remove(CORE.config_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print(color(Fore.BOLD_GREEN, "SUCCESS"))
 | 
				
			||||||
 | 
					    print()
 | 
				
			||||||
 | 
					    return 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PRE_CONFIG_ACTIONS = {
 | 
					PRE_CONFIG_ACTIONS = {
 | 
				
			||||||
    "wizard": command_wizard,
 | 
					    "wizard": command_wizard,
 | 
				
			||||||
    "version": command_version,
 | 
					    "version": command_version,
 | 
				
			||||||
@@ -497,6 +620,7 @@ POST_CONFIG_ACTIONS = {
 | 
				
			|||||||
    "mqtt-fingerprint": command_mqtt_fingerprint,
 | 
					    "mqtt-fingerprint": command_mqtt_fingerprint,
 | 
				
			||||||
    "clean": command_clean,
 | 
					    "clean": command_clean,
 | 
				
			||||||
    "idedata": command_idedata,
 | 
					    "idedata": command_idedata,
 | 
				
			||||||
 | 
					    "rename": command_rename,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -564,6 +688,10 @@ def parse_args(argv):
 | 
				
			|||||||
        "--device",
 | 
					        "--device",
 | 
				
			||||||
        help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
 | 
					        help="Manually specify the serial port/address to use, for example /dev/ttyUSB0.",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    parser_upload.add_argument(
 | 
				
			||||||
 | 
					        "--file",
 | 
				
			||||||
 | 
					        help="Manually specify the binary file to upload.",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parser_logs = subparsers.add_parser(
 | 
					    parser_logs = subparsers.add_parser(
 | 
				
			||||||
        "logs",
 | 
					        "logs",
 | 
				
			||||||
@@ -607,10 +735,7 @@ def parse_args(argv):
 | 
				
			|||||||
        "wizard",
 | 
					        "wizard",
 | 
				
			||||||
        help="A helpful setup wizard that will guide you through setting up ESPHome.",
 | 
					        help="A helpful setup wizard that will guide you through setting up ESPHome.",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_wizard.add_argument(
 | 
					    parser_wizard.add_argument("configuration", help="Your YAML configuration file.")
 | 
				
			||||||
        "configuration",
 | 
					 | 
				
			||||||
        help="Your YAML configuration file.",
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parser_fingerprint = subparsers.add_parser(
 | 
					    parser_fingerprint = subparsers.add_parser(
 | 
				
			||||||
        "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker."
 | 
					        "mqtt-fingerprint", help="Get the SSL fingerprint from a MQTT broker."
 | 
				
			||||||
@@ -632,8 +757,7 @@ def parse_args(argv):
 | 
				
			|||||||
        "dashboard", help="Create a simple web server for a dashboard."
 | 
					        "dashboard", help="Create a simple web server for a dashboard."
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "configuration",
 | 
					        "configuration", help="Your YAML configuration file directory."
 | 
				
			||||||
        help="Your YAML configuration file directory.",
 | 
					 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--port",
 | 
					        "--port",
 | 
				
			||||||
@@ -641,6 +765,12 @@ def parse_args(argv):
 | 
				
			|||||||
        type=int,
 | 
					        type=int,
 | 
				
			||||||
        default=6052,
 | 
					        default=6052,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
 | 
					        "--address",
 | 
				
			||||||
 | 
					        help="The address to bind to.",
 | 
				
			||||||
 | 
					        type=str,
 | 
				
			||||||
 | 
					        default="0.0.0.0",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--username",
 | 
					        "--username",
 | 
				
			||||||
        help="The optional username to require for authentication.",
 | 
					        help="The optional username to require for authentication.",
 | 
				
			||||||
@@ -657,7 +787,7 @@ def parse_args(argv):
 | 
				
			|||||||
        "--open-ui", help="Open the dashboard UI in a browser.", action="store_true"
 | 
					        "--open-ui", help="Open the dashboard UI in a browser.", action="store_true"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--hassio", help=argparse.SUPPRESS, action="store_true"
 | 
					        "--ha-addon", help=argparse.SUPPRESS, action="store_true"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser_dashboard.add_argument(
 | 
					    parser_dashboard.add_argument(
 | 
				
			||||||
        "--socket", help="Make the dashboard serve under a unix socket", type=str
 | 
					        "--socket", help="Make the dashboard serve under a unix socket", type=str
 | 
				
			||||||
@@ -677,6 +807,15 @@ def parse_args(argv):
 | 
				
			|||||||
        "configuration", help="Your YAML configuration file(s).", nargs=1
 | 
					        "configuration", help="Your YAML configuration file(s).", nargs=1
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser_rename = subparsers.add_parser(
 | 
				
			||||||
 | 
					        "rename",
 | 
				
			||||||
 | 
					        help="Rename a device in YAML, compile the binary and upload it.",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    parser_rename.add_argument(
 | 
				
			||||||
 | 
					        "configuration", help="Your YAML configuration file.", nargs=1
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    parser_rename.add_argument("name", help="The new name for the device.", type=str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Keep backward compatibility with the old command line format of
 | 
					    # Keep backward compatibility with the old command line format of
 | 
				
			||||||
    # esphome <config> <command>.
 | 
					    # esphome <config> <command>.
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
@@ -774,10 +913,10 @@ def run_esphome(argv):
 | 
				
			|||||||
        _LOGGER.warning("Please instead use:")
 | 
					        _LOGGER.warning("Please instead use:")
 | 
				
			||||||
        _LOGGER.warning("   esphome %s", " ".join(args.deprecated_argv_suggestion))
 | 
					        _LOGGER.warning("   esphome %s", " ".join(args.deprecated_argv_suggestion))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if sys.version_info < (3, 7, 0):
 | 
					    if sys.version_info < (3, 8, 0):
 | 
				
			||||||
        _LOGGER.error(
 | 
					        _LOGGER.error(
 | 
				
			||||||
            "You're running ESPHome with Python <3.7. ESPHome is no longer compatible "
 | 
					            "You're running ESPHome with Python <3.8. ESPHome is no longer compatible "
 | 
				
			||||||
            "with this Python version. Please reinstall ESPHome with Python 3.7+"
 | 
					            "with this Python version. Please reinstall ESPHome with Python 3.8+"
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        return 1
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -789,6 +928,10 @@ def run_esphome(argv):
 | 
				
			|||||||
            return 1
 | 
					            return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for conf_path in args.configuration:
 | 
					    for conf_path in args.configuration:
 | 
				
			||||||
 | 
					        if any(os.path.basename(conf_path) == x for x in SECRETS_FILES):
 | 
				
			||||||
 | 
					            _LOGGER.warning("Skipping secrets file %s", conf_path)
 | 
				
			||||||
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CORE.config_path = conf_path
 | 
					        CORE.config_path = conf_path
 | 
				
			||||||
        CORE.dashboard = args.dashboard
 | 
					        CORE.dashboard = args.dashboard
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ from esphome.const import (
 | 
				
			|||||||
    CONF_TYPE_ID,
 | 
					    CONF_TYPE_ID,
 | 
				
			||||||
    CONF_TIME,
 | 
					    CONF_TIME,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from esphome.jsonschema import jschema_extractor
 | 
					from esphome.schema_extractors import SCHEMA_EXTRACT, schema_extractor
 | 
				
			||||||
from esphome.util import Registry
 | 
					from esphome.util import Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,11 +23,10 @@ def maybe_simple_id(*validators):
 | 
				
			|||||||
def maybe_conf(conf, *validators):
 | 
					def maybe_conf(conf, *validators):
 | 
				
			||||||
    validator = cv.All(*validators)
 | 
					    validator = cv.All(*validators)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @jschema_extractor("maybe")
 | 
					    @schema_extractor("maybe")
 | 
				
			||||||
    def validate(value):
 | 
					    def validate(value):
 | 
				
			||||||
        # pylint: disable=comparison-with-callable
 | 
					        if value == SCHEMA_EXTRACT:
 | 
				
			||||||
        if value == jschema_extractor:
 | 
					            return (validator, conf)
 | 
				
			||||||
            return validator
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if isinstance(value, dict):
 | 
					        if isinstance(value, dict):
 | 
				
			||||||
            return validator(value)
 | 
					            return validator(value)
 | 
				
			||||||
@@ -111,11 +110,9 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False):
 | 
				
			|||||||
        # This should only happen with invalid configs, but let's have a nice error message.
 | 
					        # This should only happen with invalid configs, but let's have a nice error message.
 | 
				
			||||||
        return [schema(value)]
 | 
					        return [schema(value)]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @jschema_extractor("automation")
 | 
					    @schema_extractor("automation")
 | 
				
			||||||
    def validator(value):
 | 
					    def validator(value):
 | 
				
			||||||
        # hack to get the schema
 | 
					        if value == SCHEMA_EXTRACT:
 | 
				
			||||||
        # pylint: disable=comparison-with-callable
 | 
					 | 
				
			||||||
        if value == jschema_extractor:
 | 
					 | 
				
			||||||
            return schema
 | 
					            return schema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        value = validator_(value)
 | 
					        value = validator_(value)
 | 
				
			||||||
@@ -262,21 +259,16 @@ async def repeat_action_to_code(config, action_id, template_arg, args):
 | 
				
			|||||||
    return var
 | 
					    return var
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def validate_wait_until(value):
 | 
					_validate_wait_until = cv.maybe_simple_value(
 | 
				
			||||||
    schema = cv.Schema(
 | 
					    {
 | 
				
			||||||
        {
 | 
					        cv.Required(CONF_CONDITION): validate_potentially_and_condition,
 | 
				
			||||||
            cv.Required(CONF_CONDITION): validate_potentially_and_condition,
 | 
					        cv.Optional(CONF_TIMEOUT): cv.templatable(cv.positive_time_period_milliseconds),
 | 
				
			||||||
            cv.Optional(CONF_TIMEOUT): cv.templatable(
 | 
					    },
 | 
				
			||||||
                cv.positive_time_period_milliseconds
 | 
					    key=CONF_CONDITION,
 | 
				
			||||||
            ),
 | 
					)
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    if isinstance(value, dict) and CONF_CONDITION in value:
 | 
					 | 
				
			||||||
        return schema(value)
 | 
					 | 
				
			||||||
    return validate_wait_until({CONF_CONDITION: value})
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@register_action("wait_until", WaitUntilAction, validate_wait_until)
 | 
					@register_action("wait_until", WaitUntilAction, _validate_wait_until)
 | 
				
			||||||
async def wait_until_action_to_code(config, action_id, template_arg, args):
 | 
					async def wait_until_action_to_code(config, action_id, template_arg, args):
 | 
				
			||||||
    conditions = await build_condition(config[CONF_CONDITION], template_arg, args)
 | 
					    conditions = await build_condition(config[CONF_CONDITION], template_arg, args)
 | 
				
			||||||
    var = cg.new_Pvariable(action_id, template_arg, conditions)
 | 
					    var = cg.new_Pvariable(action_id, template_arg, conditions)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,6 +22,7 @@ from esphome.cpp_generator import (  # noqa
 | 
				
			|||||||
    static_const_array,
 | 
					    static_const_array,
 | 
				
			||||||
    statement,
 | 
					    statement,
 | 
				
			||||||
    variable,
 | 
					    variable,
 | 
				
			||||||
 | 
					    with_local_variable,
 | 
				
			||||||
    new_variable,
 | 
					    new_variable,
 | 
				
			||||||
    Pvariable,
 | 
					    Pvariable,
 | 
				
			||||||
    new_Pvariable,
 | 
					    new_Pvariable,
 | 
				
			||||||
@@ -63,6 +64,8 @@ from esphome.cpp_types import (  # noqa
 | 
				
			|||||||
    uint32,
 | 
					    uint32,
 | 
				
			||||||
    uint64,
 | 
					    uint64,
 | 
				
			||||||
    int32,
 | 
					    int32,
 | 
				
			||||||
 | 
					    int64,
 | 
				
			||||||
 | 
					    size_t,
 | 
				
			||||||
    const_char_ptr,
 | 
					    const_char_ptr,
 | 
				
			||||||
    NAN,
 | 
					    NAN,
 | 
				
			||||||
    esphome_ns,
 | 
					    esphome_ns,
 | 
				
			||||||
@@ -75,11 +78,11 @@ from esphome.cpp_types import (  # noqa
 | 
				
			|||||||
    optional,
 | 
					    optional,
 | 
				
			||||||
    arduino_json_ns,
 | 
					    arduino_json_ns,
 | 
				
			||||||
    JsonObject,
 | 
					    JsonObject,
 | 
				
			||||||
    JsonObjectRef,
 | 
					    JsonObjectConst,
 | 
				
			||||||
    JsonObjectConstRef,
 | 
					 | 
				
			||||||
    Controller,
 | 
					    Controller,
 | 
				
			||||||
    GPIOPin,
 | 
					    GPIOPin,
 | 
				
			||||||
    InternalGPIOPin,
 | 
					    InternalGPIOPin,
 | 
				
			||||||
    gpio_Flags,
 | 
					    gpio_Flags,
 | 
				
			||||||
    EntityCategory,
 | 
					    EntityCategory,
 | 
				
			||||||
 | 
					    Parented,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,10 +52,10 @@ uint32_t IRAM_ATTR HOT AcDimmerDataStore::timer_intr(uint32_t now) {
 | 
				
			|||||||
    this->gate_pin.digital_write(false);
 | 
					    this->gate_pin.digital_write(false);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (time_since_zc < this->enable_time_us)
 | 
					  if (time_since_zc < this->enable_time_us) {
 | 
				
			||||||
    // Next event is enable, return time until that event
 | 
					    // Next event is enable, return time until that event
 | 
				
			||||||
    return this->enable_time_us - time_since_zc;
 | 
					    return this->enable_time_us - time_since_zc;
 | 
				
			||||||
  else if (time_since_zc < disable_time_us) {
 | 
					  } else if (time_since_zc < disable_time_us) {
 | 
				
			||||||
    // Next event is disable, return time until that event
 | 
					    // Next event is disable, return time until that event
 | 
				
			||||||
    return this->disable_time_us - time_since_zc;
 | 
					    return this->disable_time_us - time_since_zc;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -74,9 +74,10 @@ uint32_t IRAM_ATTR HOT timer_interrupt() {
 | 
				
			|||||||
  uint32_t min_dt_us = 1000;
 | 
					  uint32_t min_dt_us = 1000;
 | 
				
			||||||
  uint32_t now = micros();
 | 
					  uint32_t now = micros();
 | 
				
			||||||
  for (auto *dimmer : all_dimmers) {
 | 
					  for (auto *dimmer : all_dimmers) {
 | 
				
			||||||
    if (dimmer == nullptr)
 | 
					    if (dimmer == nullptr) {
 | 
				
			||||||
      // no more dimmers
 | 
					      // no more dimmers
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    uint32_t res = dimmer->timer_intr(now);
 | 
					    uint32_t res = dimmer->timer_intr(now);
 | 
				
			||||||
    if (res != 0 && res < min_dt_us)
 | 
					    if (res != 0 && res < min_dt_us)
 | 
				
			||||||
      min_dt_us = res;
 | 
					      min_dt_us = res;
 | 
				
			||||||
@@ -121,6 +122,7 @@ void IRAM_ATTR HOT AcDimmerDataStore::gpio_intr() {
 | 
				
			|||||||
      // also take into account min_power
 | 
					      // also take into account min_power
 | 
				
			||||||
      auto min_us = this->cycle_time_us * this->min_power / 1000;
 | 
					      auto min_us = this->cycle_time_us * this->min_power / 1000;
 | 
				
			||||||
      this->enable_time_us = std::max((uint32_t) 1, ((65535 - this->value) * (this->cycle_time_us - min_us)) / 65535);
 | 
					      this->enable_time_us = std::max((uint32_t) 1, ((65535 - this->value) * (this->cycle_time_us - min_us)) / 65535);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (this->method == DIM_METHOD_LEADING_PULSE) {
 | 
					      if (this->method == DIM_METHOD_LEADING_PULSE) {
 | 
				
			||||||
        // Minimum pulse time should be enough for the triac to trigger when it is close to the ZC zone
 | 
					        // Minimum pulse time should be enough for the triac to trigger when it is close to the ZC zone
 | 
				
			||||||
        // this is for brightness near 99%
 | 
					        // this is for brightness near 99%
 | 
				
			||||||
@@ -201,6 +203,7 @@ void AcDimmer::setup() {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void AcDimmer::write_state(float state) {
 | 
					void AcDimmer::write_state(float state) {
 | 
				
			||||||
 | 
					  state = std::acos(1 - (2 * state)) / 3.14159;  // RMS power compensation
 | 
				
			||||||
  auto new_value = static_cast<uint16_t>(roundf(state * 65535));
 | 
					  auto new_value = static_cast<uint16_t>(roundf(state * 65535));
 | 
				
			||||||
  if (new_value != 0 && this->store_.value == 0)
 | 
					  if (new_value != 0 && this->store_.value == 0)
 | 
				
			||||||
    this->store_.init_cycle = this->init_with_half_cycle_;
 | 
					    this->store_.init_cycle = this->init_with_half_cycle_;
 | 
				
			||||||
@@ -212,12 +215,13 @@ void AcDimmer::dump_config() {
 | 
				
			|||||||
  LOG_PIN("  Zero-Cross Pin: ", this->zero_cross_pin_);
 | 
					  LOG_PIN("  Zero-Cross Pin: ", this->zero_cross_pin_);
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "   Min Power: %.1f%%", this->store_.min_power / 10.0f);
 | 
					  ESP_LOGCONFIG(TAG, "   Min Power: %.1f%%", this->store_.min_power / 10.0f);
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "   Init with half cycle: %s", YESNO(this->init_with_half_cycle_));
 | 
					  ESP_LOGCONFIG(TAG, "   Init with half cycle: %s", YESNO(this->init_with_half_cycle_));
 | 
				
			||||||
  if (method_ == DIM_METHOD_LEADING_PULSE)
 | 
					  if (method_ == DIM_METHOD_LEADING_PULSE) {
 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "   Method: leading pulse");
 | 
					    ESP_LOGCONFIG(TAG, "   Method: leading pulse");
 | 
				
			||||||
  else if (method_ == DIM_METHOD_LEADING)
 | 
					  } else if (method_ == DIM_METHOD_LEADING) {
 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "   Method: leading");
 | 
					    ESP_LOGCONFIG(TAG, "   Method: leading");
 | 
				
			||||||
  else
 | 
					  } else {
 | 
				
			||||||
    ESP_LOGCONFIG(TAG, "   Method: trailing");
 | 
					    ESP_LOGCONFIG(TAG, "   Method: trailing");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  LOG_FLOAT_OUTPUT(this);
 | 
					  LOG_FLOAT_OUTPUT(this);
 | 
				
			||||||
  ESP_LOGV(TAG, "  Estimated Frequency: %.3fHz", 1e6f / this->store_.cycle_time_us / 2);
 | 
					  ESP_LOGV(TAG, "  Estimated Frequency: %.3fHz", 1e6f / this->store_.cycle_time_us / 2);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,7 +25,7 @@ void AdalightLightEffect::stop() {
 | 
				
			|||||||
  AddressableLightEffect::stop();
 | 
					  AddressableLightEffect::stop();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int AdalightLightEffect::get_frame_size_(int led_count) const {
 | 
					unsigned int AdalightLightEffect::get_frame_size_(int led_count) const {
 | 
				
			||||||
  // 3 bytes: Ada
 | 
					  // 3 bytes: Ada
 | 
				
			||||||
  // 2 bytes: LED count
 | 
					  // 2 bytes: LED count
 | 
				
			||||||
  // 1 byte: checksum
 | 
					  // 1 byte: checksum
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -13,7 +13,6 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
 | 
				
			|||||||
 public:
 | 
					 public:
 | 
				
			||||||
  AdalightLightEffect(const std::string &name);
 | 
					  AdalightLightEffect(const std::string &name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 public:
 | 
					 | 
				
			||||||
  void start() override;
 | 
					  void start() override;
 | 
				
			||||||
  void stop() override;
 | 
					  void stop() override;
 | 
				
			||||||
  void apply(light::AddressableLight &it, const Color ¤t_color) override;
 | 
					  void apply(light::AddressableLight &it, const Color ¤t_color) override;
 | 
				
			||||||
@@ -25,12 +24,11 @@ class AdalightLightEffect : public light::AddressableLightEffect, public uart::U
 | 
				
			|||||||
    CONSUMED,
 | 
					    CONSUMED,
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int get_frame_size_(int led_count) const;
 | 
					  unsigned int get_frame_size_(int led_count) const;
 | 
				
			||||||
  void reset_frame_(light::AddressableLight &it);
 | 
					  void reset_frame_(light::AddressableLight &it);
 | 
				
			||||||
  void blank_all_leds_(light::AddressableLight &it);
 | 
					  void blank_all_leds_(light::AddressableLight &it);
 | 
				
			||||||
  Frame parse_frame_(light::AddressableLight &it);
 | 
					  Frame parse_frame_(light::AddressableLight &it);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 | 
				
			||||||
  uint32_t last_ack_{0};
 | 
					  uint32_t last_ack_{0};
 | 
				
			||||||
  uint32_t last_byte_{0};
 | 
					  uint32_t last_byte_{0};
 | 
				
			||||||
  uint32_t last_reset_{0};
 | 
					  uint32_t last_reset_{0};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,26 +11,50 @@ ADC_MODE(ADC_VCC)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					#include <hardware/adc.h>
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace adc {
 | 
					namespace adc {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *const TAG = "adc";
 | 
					static const char *const TAG = "adc";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ADCSensor::setup() {
 | 
					// 13bit for S2, and 12bit for all other esp32 variants
 | 
				
			||||||
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
 | 
					static const adc_bits_width_t ADC_WIDTH_MAX_SOC_BITS = static_cast<adc_bits_width_t>(ADC_WIDTH_MAX - 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SOC_ADC_RTC_MAX_BITWIDTH
 | 
				
			||||||
 | 
					#if USE_ESP32_VARIANT_ESP32S2
 | 
				
			||||||
 | 
					static const int SOC_ADC_RTC_MAX_BITWIDTH = 13;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					static const int SOC_ADC_RTC_MAX_BITWIDTH = 12;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const int ADC_MAX = (1 << SOC_ADC_RTC_MAX_BITWIDTH) - 1;    // 4095 (12 bit) or 8191 (13 bit)
 | 
				
			||||||
 | 
					static const int ADC_HALF = (1 << SOC_ADC_RTC_MAX_BITWIDTH) >> 1;  // 2048 (12 bit) or 4096 (13 bit)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					extern "C"
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					    void
 | 
				
			||||||
 | 
					    ADCSensor::setup() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
 | 
					  ESP_LOGCONFIG(TAG, "Setting up ADC '%s'...", this->get_name().c_str());
 | 
				
			||||||
#ifndef USE_ADC_SENSOR_VCC
 | 
					#if !defined(USE_ADC_SENSOR_VCC) && !defined(USE_RP2040)
 | 
				
			||||||
  pin_->setup();
 | 
					  pin_->setup();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  adc1_config_width(ADC_WIDTH_BIT_12);
 | 
					  adc1_config_width(ADC_WIDTH_MAX_SOC_BITS);
 | 
				
			||||||
  if (!autorange_) {
 | 
					  if (!autorange_) {
 | 
				
			||||||
    adc1_config_channel_atten(channel_, attenuation_);
 | 
					    adc1_config_channel_atten(channel_, attenuation_);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // load characteristics for each attenuation
 | 
					  // load characteristics for each attenuation
 | 
				
			||||||
  for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) {
 | 
					  for (int i = 0; i < (int) ADC_ATTEN_MAX; i++) {
 | 
				
			||||||
    auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_BIT_12,
 | 
					    auto cal_value = esp_adc_cal_characterize(ADC_UNIT_1, (adc_atten_t) i, ADC_WIDTH_MAX_SOC_BITS,
 | 
				
			||||||
                                              1100,  // default vref
 | 
					                                              1100,  // default vref
 | 
				
			||||||
                                              &cal_characteristics_[i]);
 | 
					                                              &cal_characteristics_[i]);
 | 
				
			||||||
    switch (cal_value) {
 | 
					    switch (cal_value) {
 | 
				
			||||||
@@ -46,11 +70,17 @@ void ADCSensor::setup() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // adc_gpio_init doesn't exist on ESP32-C3 or ESP32-H2
 | 
					 | 
				
			||||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32H2)
 | 
					 | 
				
			||||||
  adc_gpio_init(ADC_UNIT_1, (adc_channel_t) channel_);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
#endif  // USE_ESP32
 | 
					#endif  // USE_ESP32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					  static bool initialized = false;
 | 
				
			||||||
 | 
					  if (!initialized) {
 | 
				
			||||||
 | 
					    adc_init();
 | 
				
			||||||
 | 
					    initialized = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "ADC '%s' setup finished!", this->get_name().c_str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void ADCSensor::dump_config() {
 | 
					void ADCSensor::dump_config() {
 | 
				
			||||||
@@ -65,33 +95,41 @@ void ADCSensor::dump_config() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  LOG_PIN("  Pin: ", pin_);
 | 
					  LOG_PIN("  Pin: ", pin_);
 | 
				
			||||||
  if (autorange_)
 | 
					  if (autorange_) {
 | 
				
			||||||
    ESP_LOGCONFIG(TAG, " Attenuation: auto");
 | 
					    ESP_LOGCONFIG(TAG, " Attenuation: auto");
 | 
				
			||||||
  else
 | 
					  } else {
 | 
				
			||||||
    switch (this->attenuation_) {
 | 
					    switch (this->attenuation_) {
 | 
				
			||||||
      case ADC_ATTEN_DB_0:
 | 
					      case ADC_ATTEN_DB_0:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 0db (max 1.1V)");
 | 
					        ESP_LOGCONFIG(TAG, " Attenuation: 0db");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case ADC_ATTEN_DB_2_5:
 | 
					      case ADC_ATTEN_DB_2_5:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 2.5db (max 1.5V)");
 | 
					        ESP_LOGCONFIG(TAG, " Attenuation: 2.5db");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case ADC_ATTEN_DB_6:
 | 
					      case ADC_ATTEN_DB_6:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 6db (max 2.2V)");
 | 
					        ESP_LOGCONFIG(TAG, " Attenuation: 6db");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      case ADC_ATTEN_DB_11:
 | 
					      case ADC_ATTEN_DB_11:
 | 
				
			||||||
        ESP_LOGCONFIG(TAG, " Attenuation: 11db (max 3.9V)");
 | 
					        ESP_LOGCONFIG(TAG, " Attenuation: 11db");
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
					      default:  // This is to satisfy the unused ADC_ATTEN_MAX
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
#endif  // USE_ESP32
 | 
					#endif  // USE_ESP32
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					  if (this->is_temperature_) {
 | 
				
			||||||
 | 
					    ESP_LOGCONFIG(TAG, "  Pin: Temperature");
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    LOG_PIN("  Pin: ", pin_);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  LOG_UPDATE_INTERVAL(this);
 | 
					  LOG_UPDATE_INTERVAL(this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
 | 
					float ADCSensor::get_setup_priority() const { return setup_priority::DATA; }
 | 
				
			||||||
void ADCSensor::update() {
 | 
					void ADCSensor::update() {
 | 
				
			||||||
  float value_v = this->sample();
 | 
					  float value_v = this->sample();
 | 
				
			||||||
  ESP_LOGD(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v);
 | 
					  ESP_LOGV(TAG, "'%s': Got voltage=%.4fV", this->get_name().c_str(), value_v);
 | 
				
			||||||
  this->publish_state(value_v);
 | 
					  this->publish_state(value_v);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -123,16 +161,16 @@ float ADCSensor::sample() {
 | 
				
			|||||||
    return mv / 1000.0f;
 | 
					    return mv / 1000.0f;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int raw11, raw6 = 4095, raw2 = 4095, raw0 = 4095;
 | 
					  int raw11, raw6 = ADC_MAX, raw2 = ADC_MAX, raw0 = ADC_MAX;
 | 
				
			||||||
  adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11);
 | 
					  adc1_config_channel_atten(channel_, ADC_ATTEN_DB_11);
 | 
				
			||||||
  raw11 = adc1_get_raw(channel_);
 | 
					  raw11 = adc1_get_raw(channel_);
 | 
				
			||||||
  if (raw11 < 4095) {
 | 
					  if (raw11 < ADC_MAX) {
 | 
				
			||||||
    adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6);
 | 
					    adc1_config_channel_atten(channel_, ADC_ATTEN_DB_6);
 | 
				
			||||||
    raw6 = adc1_get_raw(channel_);
 | 
					    raw6 = adc1_get_raw(channel_);
 | 
				
			||||||
    if (raw6 < 4095) {
 | 
					    if (raw6 < ADC_MAX) {
 | 
				
			||||||
      adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5);
 | 
					      adc1_config_channel_atten(channel_, ADC_ATTEN_DB_2_5);
 | 
				
			||||||
      raw2 = adc1_get_raw(channel_);
 | 
					      raw2 = adc1_get_raw(channel_);
 | 
				
			||||||
      if (raw2 < 4095) {
 | 
					      if (raw2 < ADC_MAX) {
 | 
				
			||||||
        adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0);
 | 
					        adc1_config_channel_atten(channel_, ADC_ATTEN_DB_0);
 | 
				
			||||||
        raw0 = adc1_get_raw(channel_);
 | 
					        raw0 = adc1_get_raw(channel_);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -148,20 +186,43 @@ float ADCSensor::sample() {
 | 
				
			|||||||
  uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]);
 | 
					  uint32_t mv2 = esp_adc_cal_raw_to_voltage(raw2, &cal_characteristics_[(int) ADC_ATTEN_DB_2_5]);
 | 
				
			||||||
  uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]);
 | 
					  uint32_t mv0 = esp_adc_cal_raw_to_voltage(raw0, &cal_characteristics_[(int) ADC_ATTEN_DB_0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Contribution of each value, in range 0-2048
 | 
					  // Contribution of each value, in range 0-2048 (12 bit ADC) or 0-4096 (13 bit ADC)
 | 
				
			||||||
  uint32_t c11 = std::min(raw11, 2048);
 | 
					  uint32_t c11 = std::min(raw11, ADC_HALF);
 | 
				
			||||||
  uint32_t c6 = 2048 - std::abs(raw6 - 2048);
 | 
					  uint32_t c6 = ADC_HALF - std::abs(raw6 - ADC_HALF);
 | 
				
			||||||
  uint32_t c2 = 2048 - std::abs(raw2 - 2048);
 | 
					  uint32_t c2 = ADC_HALF - std::abs(raw2 - ADC_HALF);
 | 
				
			||||||
  uint32_t c0 = std::min(4095 - raw0, 2048);
 | 
					  uint32_t c0 = std::min(ADC_MAX - raw0, ADC_HALF);
 | 
				
			||||||
  // max theoretical csum value is 2048*4 = 8192
 | 
					  // max theoretical csum value is 4096*4 = 16384
 | 
				
			||||||
  uint32_t csum = c11 + c6 + c2 + c0;
 | 
					  uint32_t csum = c11 + c6 + c2 + c0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // each mv is max 3900; so max value is 3900*2048*4, fits in unsigned
 | 
					  // each mv is max 3900; so max value is 3900*4096*4, fits in unsigned32
 | 
				
			||||||
  uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0);
 | 
					  uint32_t mv_scaled = (mv11 * c11) + (mv6 * c6) + (mv2 * c2) + (mv0 * c0);
 | 
				
			||||||
  return mv_scaled / (float) (csum * 1000U);
 | 
					  return mv_scaled / (float) (csum * 1000U);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif  // USE_ESP32
 | 
					#endif  // USE_ESP32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					float ADCSensor::sample() {
 | 
				
			||||||
 | 
					  if (this->is_temperature_) {
 | 
				
			||||||
 | 
					    adc_set_temp_sensor_enabled(true);
 | 
				
			||||||
 | 
					    delay(1);
 | 
				
			||||||
 | 
					    adc_select_input(4);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    uint8_t pin = this->pin_->get_pin();
 | 
				
			||||||
 | 
					    adc_gpio_init(pin);
 | 
				
			||||||
 | 
					    adc_select_input(pin - 26);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int raw = adc_read();
 | 
				
			||||||
 | 
					  if (this->is_temperature_) {
 | 
				
			||||||
 | 
					    adc_set_temp_sensor_enabled(false);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (output_raw_) {
 | 
				
			||||||
 | 
					    return raw;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return raw * 3.3f / 4096.0f;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP8266
 | 
					#ifdef USE_ESP8266
 | 
				
			||||||
std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
 | 
					std::string ADCSensor::unique_id() { return get_mac_address() + "-adc"; }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,10 +38,18 @@ class ADCSensor : public sensor::Sensor, public PollingComponent, public voltage
 | 
				
			|||||||
  std::string unique_id() override;
 | 
					  std::string unique_id() override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					  void set_is_temperature() { is_temperature_ = true; }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  InternalGPIOPin *pin_;
 | 
					  InternalGPIOPin *pin_;
 | 
				
			||||||
  bool output_raw_{false};
 | 
					  bool output_raw_{false};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_RP2040
 | 
				
			||||||
 | 
					  bool is_temperature_{false};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32
 | 
					#ifdef USE_ESP32
 | 
				
			||||||
  adc_atten_t attenuation_{ADC_ATTEN_DB_0};
 | 
					  adc_atten_t attenuation_{ADC_ATTEN_DB_0};
 | 
				
			||||||
  adc1_channel_t channel_{};
 | 
					  adc1_channel_t channel_{};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -94,6 +94,9 @@ def validate_adc_pin(value):
 | 
				
			|||||||
    if str(value).upper() == "VCC":
 | 
					    if str(value).upper() == "VCC":
 | 
				
			||||||
        return cv.only_on_esp8266("VCC")
 | 
					        return cv.only_on_esp8266("VCC")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if str(value).upper() == "TEMPERATURE":
 | 
				
			||||||
 | 
					        return cv.only_on_rp2040("TEMPERATURE")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if CORE.is_esp32:
 | 
					    if CORE.is_esp32:
 | 
				
			||||||
        value = pins.internal_gpio_input_pin_number(value)
 | 
					        value = pins.internal_gpio_input_pin_number(value)
 | 
				
			||||||
        variant = get_esp32_variant()
 | 
					        variant = get_esp32_variant()
 | 
				
			||||||
@@ -117,6 +120,12 @@ def validate_adc_pin(value):
 | 
				
			|||||||
            {CONF_ANALOG: True, CONF_INPUT: True}, internal=True
 | 
					            {CONF_ANALOG: True, CONF_INPUT: True}, internal=True
 | 
				
			||||||
        )(value)
 | 
					        )(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if CORE.is_rp2040:
 | 
				
			||||||
 | 
					        value = pins.internal_gpio_input_pin_number(value)
 | 
				
			||||||
 | 
					        if value not in (26, 27, 28, 29):
 | 
				
			||||||
 | 
					            raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC.")
 | 
				
			||||||
 | 
					        return pins.internal_gpio_input_pin_schema(value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    raise NotImplementedError
 | 
					    raise NotImplementedError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -133,6 +142,7 @@ ADCSensor = adc_ns.class_(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CONFIG_SCHEMA = cv.All(
 | 
					CONFIG_SCHEMA = cv.All(
 | 
				
			||||||
    sensor.sensor_schema(
 | 
					    sensor.sensor_schema(
 | 
				
			||||||
 | 
					        ADCSensor,
 | 
				
			||||||
        unit_of_measurement=UNIT_VOLT,
 | 
					        unit_of_measurement=UNIT_VOLT,
 | 
				
			||||||
        accuracy_decimals=2,
 | 
					        accuracy_decimals=2,
 | 
				
			||||||
        device_class=DEVICE_CLASS_VOLTAGE,
 | 
					        device_class=DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
@@ -140,7 +150,6 @@ CONFIG_SCHEMA = cv.All(
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    .extend(
 | 
					    .extend(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(ADCSensor),
 | 
					 | 
				
			||||||
            cv.Required(CONF_PIN): validate_adc_pin,
 | 
					            cv.Required(CONF_PIN): validate_adc_pin,
 | 
				
			||||||
            cv.Optional(CONF_RAW, default=False): cv.boolean,
 | 
					            cv.Optional(CONF_RAW, default=False): cv.boolean,
 | 
				
			||||||
            cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
 | 
					            cv.SplitDefault(CONF_ATTENUATION, esp32="0db"): cv.All(
 | 
				
			||||||
@@ -160,6 +169,8 @@ async def to_code(config):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if config[CONF_PIN] == "VCC":
 | 
					    if config[CONF_PIN] == "VCC":
 | 
				
			||||||
        cg.add_define("USE_ADC_SENSOR_VCC")
 | 
					        cg.add_define("USE_ADC_SENSOR_VCC")
 | 
				
			||||||
 | 
					    elif config[CONF_PIN] == "TEMPERATURE":
 | 
				
			||||||
 | 
					        cg.add(var.set_is_temperature())
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
					        pin = await cg.gpio_pin_expression(config[CONF_PIN])
 | 
				
			||||||
        cg.add(var.set_pin(pin))
 | 
					        cg.add(var.set_pin(pin))
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										23
									
								
								esphome/components/adc128s102/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/adc128s102/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					import esphome.codegen as cg
 | 
				
			||||||
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
 | 
					from esphome.components import spi
 | 
				
			||||||
 | 
					from esphome.const import CONF_ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEPENDENCIES = ["spi"]
 | 
				
			||||||
 | 
					MULTI_CONF = True
 | 
				
			||||||
 | 
					CODEOWNERS = ["@DeerMaximum"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					adc128s102_ns = cg.esphome_ns.namespace("adc128s102")
 | 
				
			||||||
 | 
					ADC128S102 = adc128s102_ns.class_("ADC128S102", cg.Component, spi.SPIDevice)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_SCHEMA = cv.Schema(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cv.GenerateID(): cv.declare_id(ADC128S102),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					).extend(spi.spi_device_schema(cs_pin_required=True))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def to_code(config):
 | 
				
			||||||
 | 
					    var = cg.new_Pvariable(config[CONF_ID])
 | 
				
			||||||
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
 | 
					    await spi.register_spi_device(var, config)
 | 
				
			||||||
							
								
								
									
										35
									
								
								esphome/components/adc128s102/adc128s102.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								esphome/components/adc128s102/adc128s102.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#include "adc128s102.h"
 | 
				
			||||||
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace adc128s102 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *const TAG = "adc128s102";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ADC128S102::get_setup_priority() const { return setup_priority::HARDWARE; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ADC128S102::setup() {
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "Setting up adc128s102");
 | 
				
			||||||
 | 
					  this->spi_setup();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ADC128S102::dump_config() {
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "ADC128S102:");
 | 
				
			||||||
 | 
					  LOG_PIN("  CS Pin:", this->cs_);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t ADC128S102::read_data(uint8_t channel) {
 | 
				
			||||||
 | 
					  uint8_t control = channel << 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->enable();
 | 
				
			||||||
 | 
					  uint8_t adc_primary_byte = this->transfer_byte(control);
 | 
				
			||||||
 | 
					  uint8_t adc_secondary_byte = this->transfer_byte(0x00);
 | 
				
			||||||
 | 
					  this->disable();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint16_t digital_value = adc_primary_byte << 8 | adc_secondary_byte;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return digital_value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace adc128s102
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
							
								
								
									
										23
									
								
								esphome/components/adc128s102/adc128s102.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								esphome/components/adc128s102/adc128s102.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
 | 
					#include "esphome/components/spi/spi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace adc128s102 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ADC128S102 : public Component,
 | 
				
			||||||
 | 
					                   public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
 | 
				
			||||||
 | 
					                                         spi::DATA_RATE_10MHZ> {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  ADC128S102() = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void setup() override;
 | 
				
			||||||
 | 
					  void dump_config() override;
 | 
				
			||||||
 | 
					  float get_setup_priority() const override;
 | 
				
			||||||
 | 
					  uint16_t read_data(uint8_t channel);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace adc128s102
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
							
								
								
									
										35
									
								
								esphome/components/adc128s102/sensor/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								esphome/components/adc128s102/sensor/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					import esphome.codegen as cg
 | 
				
			||||||
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
 | 
					from esphome.components import sensor, voltage_sampler
 | 
				
			||||||
 | 
					from esphome.const import CONF_ID, CONF_CHANNEL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from .. import adc128s102_ns, ADC128S102
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AUTO_LOAD = ["voltage_sampler"]
 | 
				
			||||||
 | 
					DEPENDENCIES = ["adc128s102"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADC128S102Sensor = adc128s102_ns.class_(
 | 
				
			||||||
 | 
					    "ADC128S102Sensor",
 | 
				
			||||||
 | 
					    sensor.Sensor,
 | 
				
			||||||
 | 
					    cg.PollingComponent,
 | 
				
			||||||
 | 
					    voltage_sampler.VoltageSampler,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					CONF_ADC128S102_ID = "adc128s102_id"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_SCHEMA = sensor.SENSOR_SCHEMA.extend(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cv.GenerateID(): cv.declare_id(ADC128S102Sensor),
 | 
				
			||||||
 | 
					        cv.GenerateID(CONF_ADC128S102_ID): cv.use_id(ADC128S102),
 | 
				
			||||||
 | 
					        cv.Required(CONF_CHANNEL): cv.int_range(min=0, max=7),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					).extend(cv.polling_component_schema("60s"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def to_code(config):
 | 
				
			||||||
 | 
					    var = cg.new_Pvariable(
 | 
				
			||||||
 | 
					        config[CONF_ID],
 | 
				
			||||||
 | 
					        config[CONF_CHANNEL],
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    await cg.register_parented(var, config[CONF_ADC128S102_ID])
 | 
				
			||||||
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
 | 
					    await sensor.register_sensor(var, config)
 | 
				
			||||||
							
								
								
									
										24
									
								
								esphome/components/adc128s102/sensor/adc128s102_sensor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								esphome/components/adc128s102/sensor/adc128s102_sensor.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#include "adc128s102_sensor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace adc128s102 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *const TAG = "adc128s102.sensor";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADC128S102Sensor::ADC128S102Sensor(uint8_t channel) : channel_(channel) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ADC128S102Sensor::get_setup_priority() const { return setup_priority::DATA; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ADC128S102Sensor::dump_config() {
 | 
				
			||||||
 | 
					  LOG_SENSOR("", "ADC128S102 Sensor", this);
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "  Pin: %u", this->channel_);
 | 
				
			||||||
 | 
					  LOG_UPDATE_INTERVAL(this);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					float ADC128S102Sensor::sample() { return this->parent_->read_data(this->channel_); }
 | 
				
			||||||
 | 
					void ADC128S102Sensor::update() { this->publish_state(this->sample()); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace adc128s102
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
							
								
								
									
										29
									
								
								esphome/components/adc128s102/sensor/adc128s102_sensor.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								esphome/components/adc128s102/sensor/adc128s102_sensor.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esphome/components/sensor/sensor.h"
 | 
				
			||||||
 | 
					#include "esphome/components/voltage_sampler/voltage_sampler.h"
 | 
				
			||||||
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "../adc128s102.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace adc128s102 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ADC128S102Sensor : public PollingComponent,
 | 
				
			||||||
 | 
					                         public Parented<ADC128S102>,
 | 
				
			||||||
 | 
					                         public sensor::Sensor,
 | 
				
			||||||
 | 
					                         public voltage_sampler::VoltageSampler {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  ADC128S102Sensor(uint8_t channel);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void update() override;
 | 
				
			||||||
 | 
					  void dump_config() override;
 | 
				
			||||||
 | 
					  float get_setup_priority() const override;
 | 
				
			||||||
 | 
					  float sample() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  uint8_t channel_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					}  // namespace adc128s102
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include "esphome/components/display/display_buffer.h"
 | 
					#include "esphome/components/display/display_buffer.h"
 | 
				
			||||||
#include "esphome/components/light/addressable_light.h"
 | 
					#include "esphome/components/light/addressable_light.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace addressable_light {
 | 
					namespace addressable_light {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,6 +42,8 @@ class AddressableLightDisplay : public display::DisplayBuffer, public PollingCom
 | 
				
			|||||||
  void setup() override;
 | 
					  void setup() override;
 | 
				
			||||||
  void display();
 | 
					  void display();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  display::DisplayType get_display_type() override { return display::DisplayType::DISPLAY_TYPE_COLOR; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  int get_width_internal() override;
 | 
					  int get_width_internal() override;
 | 
				
			||||||
  int get_height_internal() override;
 | 
					  int get_height_internal() override;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include "esphome/components/i2c/i2c.h"
 | 
					#include "esphome/components/i2c/i2c.h"
 | 
				
			||||||
#include "esphome/components/sensor/sensor.h"
 | 
					#include "esphome/components/sensor/sensor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace ade7953 {
 | 
					namespace ade7953 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -82,7 +84,7 @@ class ADE7953 : public i2c::I2CDevice, public PollingComponent {
 | 
				
			|||||||
    return i2c::ERROR_OK;
 | 
					    return i2c::ERROR_OK;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  InternalGPIOPin *irq_pin_ = nullptr;
 | 
					  InternalGPIOPin *irq_pin_{nullptr};
 | 
				
			||||||
  bool is_setup_{false};
 | 
					  bool is_setup_{false};
 | 
				
			||||||
  sensor::Sensor *voltage_sensor_{nullptr};
 | 
					  sensor::Sensor *voltage_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *current_a_sensor_{nullptr};
 | 
					  sensor::Sensor *current_a_sensor_{nullptr};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include "esphome/components/i2c/i2c.h"
 | 
					#include "esphome/components/i2c/i2c.h"
 | 
				
			||||||
#include "esphome/components/voltage_sampler/voltage_sampler.h"
 | 
					#include "esphome/components/voltage_sampler/voltage_sampler.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace ads1115 {
 | 
					namespace ads1115 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,6 +52,7 @@ ADS1115Sensor = ads1115_ns.class_(
 | 
				
			|||||||
CONF_ADS1115_ID = "ads1115_id"
 | 
					CONF_ADS1115_ID = "ads1115_id"
 | 
				
			||||||
CONFIG_SCHEMA = (
 | 
					CONFIG_SCHEMA = (
 | 
				
			||||||
    sensor.sensor_schema(
 | 
					    sensor.sensor_schema(
 | 
				
			||||||
 | 
					        ADS1115Sensor,
 | 
				
			||||||
        unit_of_measurement=UNIT_VOLT,
 | 
					        unit_of_measurement=UNIT_VOLT,
 | 
				
			||||||
        accuracy_decimals=3,
 | 
					        accuracy_decimals=3,
 | 
				
			||||||
        device_class=DEVICE_CLASS_VOLTAGE,
 | 
					        device_class=DEVICE_CLASS_VOLTAGE,
 | 
				
			||||||
@@ -59,7 +60,6 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
    )
 | 
					    )
 | 
				
			||||||
    .extend(
 | 
					    .extend(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(ADS1115Sensor),
 | 
					 | 
				
			||||||
            cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component),
 | 
					            cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component),
 | 
				
			||||||
            cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"),
 | 
					            cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space="_"),
 | 
				
			||||||
            cv.Required(CONF_GAIN): validate_gain,
 | 
					            cv.Required(CONF_GAIN): validate_gain,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,13 +73,6 @@ void AHT10Component::update() {
 | 
				
			|||||||
  bool success = false;
 | 
					  bool success = false;
 | 
				
			||||||
  for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
 | 
					  for (int i = 0; i < AHT10_ATTEMPTS; ++i) {
 | 
				
			||||||
    ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis());
 | 
					    ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis());
 | 
				
			||||||
    delayMicroseconds(4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint8_t reg = 0;
 | 
					 | 
				
			||||||
    if (this->write(®, 1) != i2c::ERROR_OK) {
 | 
					 | 
				
			||||||
      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
					 | 
				
			||||||
      continue;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    delay(delay_ms);
 | 
					    delay(delay_ms);
 | 
				
			||||||
    if (this->read(data, 6) != i2c::ERROR_OK) {
 | 
					    if (this->read(data, 6) != i2c::ERROR_OK) {
 | 
				
			||||||
      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
					      ESP_LOGD(TAG, "Communication with AHT10 failed, waiting...");
 | 
				
			||||||
@@ -117,20 +110,21 @@ void AHT10Component::update() {
 | 
				
			|||||||
  uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
 | 
					  uint32_t raw_temperature = ((data[3] & 0x0F) << 16) | (data[4] << 8) | data[5];
 | 
				
			||||||
  uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
 | 
					  uint32_t raw_humidity = ((data[1] << 16) | (data[2] << 8) | data[3]) >> 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float temperature = ((200.0 * (float) raw_temperature) / 1048576.0) - 50.0;
 | 
					  float temperature = ((200.0f * (float) raw_temperature) / 1048576.0f) - 50.0f;
 | 
				
			||||||
  float humidity;
 | 
					  float humidity;
 | 
				
			||||||
  if (raw_humidity == 0) {  // unrealistic value
 | 
					  if (raw_humidity == 0) {  // unrealistic value
 | 
				
			||||||
    humidity = NAN;
 | 
					    humidity = NAN;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    humidity = (float) raw_humidity * 100.0 / 1048576.0;
 | 
					    humidity = (float) raw_humidity * 100.0f / 1048576.0f;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (this->temperature_sensor_ != nullptr) {
 | 
					  if (this->temperature_sensor_ != nullptr) {
 | 
				
			||||||
    this->temperature_sensor_->publish_state(temperature);
 | 
					    this->temperature_sensor_->publish_state(temperature);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (this->humidity_sensor_ != nullptr) {
 | 
					  if (this->humidity_sensor_ != nullptr) {
 | 
				
			||||||
    if (std::isnan(humidity))
 | 
					    if (std::isnan(humidity)) {
 | 
				
			||||||
      ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum");
 | 
					      ESP_LOGW(TAG, "Invalid humidity! Sensor reported 0%% Hum");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    this->humidity_sensor_->publish_state(humidity);
 | 
					    this->humidity_sensor_->publish_state(humidity);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  this->status_clear_warning();
 | 
					  this->status_clear_warning();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,8 +18,8 @@ class AHT10Component : public PollingComponent, public i2c::I2CDevice {
 | 
				
			|||||||
  void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
 | 
					  void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  sensor::Sensor *temperature_sensor_;
 | 
					  sensor::Sensor *temperature_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *humidity_sensor_;
 | 
					  sensor::Sensor *humidity_sensor_{nullptr};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace aht10
 | 
					}  // namespace aht10
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
					    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
				
			||||||
      this->handle_ = 0;
 | 
					      this->handle_ = 0;
 | 
				
			||||||
      auto chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
 | 
					      auto *chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
 | 
				
			||||||
      if (chr == nullptr) {
 | 
					      if (chr == nullptr) {
 | 
				
			||||||
        ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
 | 
					        ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
 | 
				
			||||||
                 sensors_data_characteristic_uuid_.to_string().c_str());
 | 
					                 sensors_data_characteristic_uuid_.to_string().c_str());
 | 
				
			||||||
@@ -38,7 +38,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case ESP_GATTC_READ_CHAR_EVT: {
 | 
					    case ESP_GATTC_READ_CHAR_EVT: {
 | 
				
			||||||
      if (param->read.conn_id != this->parent()->conn_id)
 | 
					      if (param->read.conn_id != this->parent()->get_conn_id())
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      if (param->read.status != ESP_GATT_OK) {
 | 
					      if (param->read.status != ESP_GATT_OK) {
 | 
				
			||||||
        ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
 | 
					        ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
 | 
				
			||||||
@@ -56,7 +56,7 @@ void AirthingsWaveMini::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AirthingsWaveMini::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
 | 
					void AirthingsWaveMini::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
 | 
				
			||||||
  auto value = (WaveMiniReadings *) raw_value;
 | 
					  auto *value = (WaveMiniReadings *) raw_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (sizeof(WaveMiniReadings) <= value_len) {
 | 
					  if (sizeof(WaveMiniReadings) <= value_len) {
 | 
				
			||||||
    this->humidity_sensor_->publish_state(value->humidity / 100.0f);
 | 
					    this->humidity_sensor_->publish_state(value->humidity / 100.0f);
 | 
				
			||||||
@@ -88,8 +88,8 @@ void AirthingsWaveMini::update() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AirthingsWaveMini::request_read_values_() {
 | 
					void AirthingsWaveMini::request_read_values_() {
 | 
				
			||||||
  auto status =
 | 
					  auto status = esp_ble_gattc_read_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->handle_,
 | 
				
			||||||
      esp_ble_gattc_read_char(this->parent()->gattc_if, this->parent()->conn_id, this->handle_, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                        ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
  if (status) {
 | 
					  if (status) {
 | 
				
			||||||
    ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
 | 
					    ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
					    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
				
			||||||
      this->handle_ = 0;
 | 
					      this->handle_ = 0;
 | 
				
			||||||
      auto chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
 | 
					      auto *chr = this->parent()->get_characteristic(service_uuid_, sensors_data_characteristic_uuid_);
 | 
				
			||||||
      if (chr == nullptr) {
 | 
					      if (chr == nullptr) {
 | 
				
			||||||
        ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
 | 
					        ESP_LOGW(TAG, "No sensor characteristic found at service %s char %s", service_uuid_.to_string().c_str(),
 | 
				
			||||||
                 sensors_data_characteristic_uuid_.to_string().c_str());
 | 
					                 sensors_data_characteristic_uuid_.to_string().c_str());
 | 
				
			||||||
@@ -38,7 +38,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case ESP_GATTC_READ_CHAR_EVT: {
 | 
					    case ESP_GATTC_READ_CHAR_EVT: {
 | 
				
			||||||
      if (param->read.conn_id != this->parent()->conn_id)
 | 
					      if (param->read.conn_id != this->parent()->get_conn_id())
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      if (param->read.status != ESP_GATT_OK) {
 | 
					      if (param->read.status != ESP_GATT_OK) {
 | 
				
			||||||
        ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
 | 
					        ESP_LOGW(TAG, "Error reading char at handle %d, status=%d", param->read.handle, param->read.status);
 | 
				
			||||||
@@ -56,7 +56,7 @@ void AirthingsWavePlus::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AirthingsWavePlus::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
 | 
					void AirthingsWavePlus::read_sensors_(uint8_t *raw_value, uint16_t value_len) {
 | 
				
			||||||
  auto value = (WavePlusReadings *) raw_value;
 | 
					  auto *value = (WavePlusReadings *) raw_value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (sizeof(WavePlusReadings) <= value_len) {
 | 
					  if (sizeof(WavePlusReadings) <= value_len) {
 | 
				
			||||||
    ESP_LOGD(TAG, "version = %d", value->version);
 | 
					    ESP_LOGD(TAG, "version = %d", value->version);
 | 
				
			||||||
@@ -109,8 +109,8 @@ void AirthingsWavePlus::update() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AirthingsWavePlus::request_read_values_() {
 | 
					void AirthingsWavePlus::request_read_values_() {
 | 
				
			||||||
  auto status =
 | 
					  auto status = esp_ble_gattc_read_char(this->parent()->get_gattc_if(), this->parent()->get_conn_id(), this->handle_,
 | 
				
			||||||
      esp_ble_gattc_read_char(this->parent()->gattc_if, this->parent()->conn_id, this->handle_, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                        ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
  if (status) {
 | 
					  if (status) {
 | 
				
			||||||
    ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
 | 
					    ESP_LOGW(TAG, "Error sending read request for sensor, status=%d", status);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,31 +4,15 @@
 | 
				
			|||||||
//  - Arduino - AM2320: https://github.com/EngDial/AM2320/blob/master/src/AM2320.cpp
 | 
					//  - Arduino - AM2320: https://github.com/EngDial/AM2320/blob/master/src/AM2320.cpp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "am2320.h"
 | 
					#include "am2320.h"
 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
#include "esphome/core/hal.h"
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
 | 
					#include "esphome/core/helpers.h"
 | 
				
			||||||
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace am2320 {
 | 
					namespace am2320 {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *const TAG = "am2320";
 | 
					static const char *const TAG = "am2320";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ---=== Calc CRC16 ===---
 | 
					 | 
				
			||||||
uint16_t crc_16(uint8_t *ptr, uint8_t length) {
 | 
					 | 
				
			||||||
  uint16_t crc = 0xFFFF;
 | 
					 | 
				
			||||||
  uint8_t i;
 | 
					 | 
				
			||||||
  //------------------------------
 | 
					 | 
				
			||||||
  while (length--) {
 | 
					 | 
				
			||||||
    crc ^= *ptr++;
 | 
					 | 
				
			||||||
    for (i = 0; i < 8; i++)
 | 
					 | 
				
			||||||
      if ((crc & 0x01) != 0) {
 | 
					 | 
				
			||||||
        crc >>= 1;
 | 
					 | 
				
			||||||
        crc ^= 0xA001;
 | 
					 | 
				
			||||||
      } else
 | 
					 | 
				
			||||||
        crc >>= 1;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return crc;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void AM2320Component::update() {
 | 
					void AM2320Component::update() {
 | 
				
			||||||
  uint8_t data[8];
 | 
					  uint8_t data[8];
 | 
				
			||||||
  data[0] = 0;
 | 
					  data[0] = 0;
 | 
				
			||||||
@@ -38,9 +22,9 @@ void AM2320Component::update() {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  float temperature = (((data[4] & 0x7F) << 8) + data[5]) / 10.0;
 | 
					  float temperature = (((data[4] & 0x7F) << 8) + data[5]) / 10.0f;
 | 
				
			||||||
  temperature = (data[4] & 0x80) ? -temperature : temperature;
 | 
					  temperature = (data[4] & 0x80) ? -temperature : temperature;
 | 
				
			||||||
  float humidity = ((data[2] << 8) + data[3]) / 10.0;
 | 
					  float humidity = ((data[2] << 8) + data[3]) / 10.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temperature, humidity);
 | 
					  ESP_LOGD(TAG, "Got temperature=%.1f°C humidity=%.1f%%", temperature, humidity);
 | 
				
			||||||
  if (this->temperature_sensor_ != nullptr)
 | 
					  if (this->temperature_sensor_ != nullptr)
 | 
				
			||||||
@@ -96,7 +80,7 @@ bool AM2320Component::read_data_(uint8_t *data) {
 | 
				
			|||||||
  checksum = data[7] << 8;
 | 
					  checksum = data[7] << 8;
 | 
				
			||||||
  checksum += data[6];
 | 
					  checksum += data[6];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (crc_16(data, 6) != checksum) {
 | 
					  if (crc16(data, 6) != checksum) {
 | 
				
			||||||
    ESP_LOGW(TAG, "AM2320 Checksum invalid!");
 | 
					    ESP_LOGW(TAG, "AM2320 Checksum invalid!");
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,8 +21,8 @@ class AM2320Component : public PollingComponent, public i2c::I2CDevice {
 | 
				
			|||||||
  bool read_data_(uint8_t *data);
 | 
					  bool read_data_(uint8_t *data);
 | 
				
			||||||
  bool read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion = 0);
 | 
					  bool read_bytes_(uint8_t a_register, uint8_t *data, uint8_t len, uint32_t conversion = 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sensor::Sensor *temperature_sensor_;
 | 
					  sensor::Sensor *temperature_sensor_{nullptr};
 | 
				
			||||||
  sensor::Sensor *humidity_sensor_;
 | 
					  sensor::Sensor *humidity_sensor_{nullptr};
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace am2320
 | 
					}  // namespace am2320
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,7 +39,7 @@ void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_i
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
					    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
				
			||||||
      auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
					      auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
				
			||||||
      if (chr == nullptr) {
 | 
					      if (chr == nullptr) {
 | 
				
			||||||
        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
					        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
				
			||||||
          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.",
 | 
					          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.",
 | 
				
			||||||
@@ -75,13 +75,14 @@ void Am43::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_i
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      if (this->current_sensor_ > 0) {
 | 
					      if (this->current_sensor_ > 0) {
 | 
				
			||||||
        if (this->illuminance_ != nullptr) {
 | 
					        if (this->illuminance_ != nullptr) {
 | 
				
			||||||
          auto packet = this->encoder_->get_light_level_request();
 | 
					          auto *packet = this->encoder_->get_light_level_request();
 | 
				
			||||||
          auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
					          auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
 | 
				
			||||||
                                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
 | 
					                                                 this->char_handle_, packet->length, packet->data,
 | 
				
			||||||
                                                 ESP_GATT_AUTH_REQ_NONE);
 | 
					                                                 ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
          if (status)
 | 
					          if (status) {
 | 
				
			||||||
            ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
 | 
					            ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
 | 
				
			||||||
                     status);
 | 
					                     status);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this->current_sensor_ = 0;
 | 
					        this->current_sensor_ = 0;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -99,12 +100,13 @@ void Am43::update() {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  if (this->current_sensor_ == 0) {
 | 
					  if (this->current_sensor_ == 0) {
 | 
				
			||||||
    if (this->battery_ != nullptr) {
 | 
					    if (this->battery_ != nullptr) {
 | 
				
			||||||
      auto packet = this->encoder_->get_battery_level_request();
 | 
					      auto *packet = this->encoder_->get_battery_level_request();
 | 
				
			||||||
      auto status =
 | 
					      auto status =
 | 
				
			||||||
          esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
					          esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
                                   packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                   packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
      if (status)
 | 
					      if (status) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
					        ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    this->current_sensor_++;
 | 
					    this->current_sensor_++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ from esphome.const import CONF_ID, CONF_PIN
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
CODEOWNERS = ["@buxtronix"]
 | 
					CODEOWNERS = ["@buxtronix"]
 | 
				
			||||||
DEPENDENCIES = ["ble_client"]
 | 
					DEPENDENCIES = ["ble_client"]
 | 
				
			||||||
AUTO_LOAD = ["am43"]
 | 
					AUTO_LOAD = ["am43", "sensor"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONF_INVERT_POSITION = "invert_position"
 | 
					CONF_INVERT_POSITION = "invert_position"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,15 +25,16 @@ void Am43Component::setup() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void Am43Component::loop() {
 | 
					void Am43Component::loop() {
 | 
				
			||||||
  if (this->node_state == espbt::ClientState::ESTABLISHED && !this->logged_in_) {
 | 
					  if (this->node_state == espbt::ClientState::ESTABLISHED && !this->logged_in_) {
 | 
				
			||||||
    auto packet = this->encoder_->get_send_pin_request(this->pin_);
 | 
					    auto *packet = this->encoder_->get_send_pin_request(this->pin_);
 | 
				
			||||||
    auto status =
 | 
					    auto status =
 | 
				
			||||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
    ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
 | 
					    ESP_LOGI(TAG, "[%s] Logging into AM43", this->get_name().c_str());
 | 
				
			||||||
    if (status)
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] Error writing set_pin to device, error = %d", this->get_name().c_str(), status);
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
      this->logged_in_ = true;
 | 
					      this->logged_in_ = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,24 +52,26 @@ void Am43Component::control(const CoverCall &call) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (call.get_stop()) {
 | 
					  if (call.get_stop()) {
 | 
				
			||||||
    auto packet = this->encoder_->get_stop_request();
 | 
					    auto *packet = this->encoder_->get_stop_request();
 | 
				
			||||||
    auto status =
 | 
					    auto status =
 | 
				
			||||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
    if (status)
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] Error writing stop command to device, error = %d", this->get_name().c_str(), status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (call.get_position().has_value()) {
 | 
					  if (call.get_position().has_value()) {
 | 
				
			||||||
    auto pos = *call.get_position();
 | 
					    auto pos = *call.get_position();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (this->invert_position_)
 | 
					    if (this->invert_position_)
 | 
				
			||||||
      pos = 1 - pos;
 | 
					      pos = 1 - pos;
 | 
				
			||||||
    auto packet = this->encoder_->get_set_position_request(100 - (uint8_t)(pos * 100));
 | 
					    auto *packet = this->encoder_->get_set_position_request(100 - (uint8_t)(pos * 100));
 | 
				
			||||||
    auto status =
 | 
					    auto status =
 | 
				
			||||||
        esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, packet->length,
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
                                 packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
    if (status)
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] Error writing set_position command to device, error = %d", this->get_name().c_str(), status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -80,7 +83,7 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
					    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
				
			||||||
      auto chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
					      auto *chr = this->parent_->get_characteristic(AM43_SERVICE_UUID, AM43_CHARACTERISTIC_UUID);
 | 
				
			||||||
      if (chr == nullptr) {
 | 
					      if (chr == nullptr) {
 | 
				
			||||||
        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
					        if (this->parent_->get_characteristic(AM43_TUYA_SERVICE_UUID, AM43_TUYA_CHARACTERISTIC_UUID) != nullptr) {
 | 
				
			||||||
          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
 | 
					          ESP_LOGE(TAG, "[%s] Detected a Tuya AM43 which is not supported, sorry.", this->get_name().c_str());
 | 
				
			||||||
@@ -91,7 +94,8 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      this->char_handle_ = chr->handle;
 | 
					      this->char_handle_ = chr->handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      auto status = esp_ble_gattc_register_for_notify(this->parent_->gattc_if, this->parent_->remote_bda, chr->handle);
 | 
					      auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
 | 
				
			||||||
 | 
					                                                      chr->handle);
 | 
				
			||||||
      if (status) {
 | 
					      if (status) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
 | 
					        ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -120,22 +124,25 @@ void Am43Component::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_
 | 
				
			|||||||
      if (this->decoder_->has_pin_response()) {
 | 
					      if (this->decoder_->has_pin_response()) {
 | 
				
			||||||
        if (this->decoder_->pin_ok_) {
 | 
					        if (this->decoder_->pin_ok_) {
 | 
				
			||||||
          ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
 | 
					          ESP_LOGI(TAG, "[%s] AM43 pin accepted.", this->get_name().c_str());
 | 
				
			||||||
          auto packet = this->encoder_->get_position_request();
 | 
					          auto *packet = this->encoder_->get_position_request();
 | 
				
			||||||
          auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
					          auto status = esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(),
 | 
				
			||||||
                                                 packet->length, packet->data, ESP_GATT_WRITE_TYPE_NO_RSP,
 | 
					                                                 this->char_handle_, packet->length, packet->data,
 | 
				
			||||||
                                                 ESP_GATT_AUTH_REQ_NONE);
 | 
					                                                 ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
          if (status)
 | 
					          if (status) {
 | 
				
			||||||
            ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
 | 
					            ESP_LOGW(TAG, "[%s] Error writing set_position to device, error = %d", this->get_name().c_str(), status);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
          ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
 | 
					          ESP_LOGW(TAG, "[%s] AM43 pin rejected!", this->get_name().c_str());
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_)
 | 
					      if (this->decoder_->has_set_position_response() && !this->decoder_->set_position_ok_) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
 | 
					        ESP_LOGW(TAG, "[%s] Got nack after sending set_position. Bad pin?", this->get_name().c_str());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_)
 | 
					      if (this->decoder_->has_set_state_response() && !this->decoder_->set_state_ok_) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
 | 
					        ESP_LOGW(TAG, "[%s] Got nack after sending set_state. Bad pin?", this->get_name().c_str());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								esphome/components/analog_threshold/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								esphome/components/analog_threshold/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					CODEOWNERS = ["@ianchi"]
 | 
				
			||||||
@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					#include "analog_threshold_binary_sensor.h"
 | 
				
			||||||
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace analog_threshold {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const char *const TAG = "analog_threshold.binary_sensor";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnalogThresholdBinarySensor::setup() {
 | 
				
			||||||
 | 
					  float sensor_value = this->sensor_->get_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // TRUE state is defined to be when sensor is >= threshold
 | 
				
			||||||
 | 
					  // so when undefined sensor value initialize to FALSE
 | 
				
			||||||
 | 
					  if (std::isnan(sensor_value)) {
 | 
				
			||||||
 | 
					    this->publish_initial_state(false);
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    this->publish_initial_state(sensor_value >= (this->lower_threshold_ + this->upper_threshold_) / 2.0f);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnalogThresholdBinarySensor::set_sensor(sensor::Sensor *analog_sensor) {
 | 
				
			||||||
 | 
					  this->sensor_ = analog_sensor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  this->sensor_->add_on_state_callback([this](float sensor_value) {
 | 
				
			||||||
 | 
					    // if there is an invalid sensor reading, ignore the change and keep the current state
 | 
				
			||||||
 | 
					    if (!std::isnan(sensor_value)) {
 | 
				
			||||||
 | 
					      this->publish_state(sensor_value >= (this->state ? this->lower_threshold_ : this->upper_threshold_));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void AnalogThresholdBinarySensor::dump_config() {
 | 
				
			||||||
 | 
					  LOG_BINARY_SENSOR("", "Analog Threshold Binary Sensor", this);
 | 
				
			||||||
 | 
					  LOG_SENSOR("  ", "Sensor", this->sensor_);
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "  Upper threshold: %.11f", this->upper_threshold_);
 | 
				
			||||||
 | 
					  ESP_LOGCONFIG(TAG, "  Lower threshold: %.11f", this->lower_threshold_);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace analog_threshold
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
 | 
					#include "esphome/components/binary_sensor/binary_sensor.h"
 | 
				
			||||||
 | 
					#include "esphome/components/sensor/sensor.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace esphome {
 | 
				
			||||||
 | 
					namespace analog_threshold {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class AnalogThresholdBinarySensor : public Component, public binary_sensor::BinarySensor {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  void dump_config() override;
 | 
				
			||||||
 | 
					  void setup() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  float get_setup_priority() const override { return setup_priority::DATA; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void set_sensor(sensor::Sensor *analog_sensor);
 | 
				
			||||||
 | 
					  void set_upper_threshold(float threshold) { this->upper_threshold_ = threshold; }
 | 
				
			||||||
 | 
					  void set_lower_threshold(float threshold) { this->lower_threshold_ = threshold; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  sensor::Sensor *sensor_{nullptr};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  float upper_threshold_;
 | 
				
			||||||
 | 
					  float lower_threshold_;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}  // namespace analog_threshold
 | 
				
			||||||
 | 
					}  // namespace esphome
 | 
				
			||||||
							
								
								
									
										44
									
								
								esphome/components/analog_threshold/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								esphome/components/analog_threshold/binary_sensor.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,44 @@
 | 
				
			|||||||
 | 
					import esphome.codegen as cg
 | 
				
			||||||
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
 | 
					from esphome.components import binary_sensor, sensor
 | 
				
			||||||
 | 
					from esphome.const import (
 | 
				
			||||||
 | 
					    CONF_SENSOR_ID,
 | 
				
			||||||
 | 
					    CONF_THRESHOLD,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					analog_threshold_ns = cg.esphome_ns.namespace("analog_threshold")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					AnalogThresholdBinarySensor = analog_threshold_ns.class_(
 | 
				
			||||||
 | 
					    "AnalogThresholdBinarySensor", binary_sensor.BinarySensor, cg.Component
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONF_UPPER = "upper"
 | 
				
			||||||
 | 
					CONF_LOWER = "lower"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        cv.GenerateID(): cv.declare_id(AnalogThresholdBinarySensor),
 | 
				
			||||||
 | 
					        cv.Required(CONF_SENSOR_ID): cv.use_id(sensor.Sensor),
 | 
				
			||||||
 | 
					        cv.Required(CONF_THRESHOLD): cv.Any(
 | 
				
			||||||
 | 
					            cv.float_,
 | 
				
			||||||
 | 
					            cv.Schema(
 | 
				
			||||||
 | 
					                {cv.Required(CONF_UPPER): cv.float_, cv.Required(CONF_LOWER): cv.float_}
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					).extend(cv.COMPONENT_SCHEMA)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async def to_code(config):
 | 
				
			||||||
 | 
					    var = await binary_sensor.new_binary_sensor(config)
 | 
				
			||||||
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    sens = await cg.get_variable(config[CONF_SENSOR_ID])
 | 
				
			||||||
 | 
					    cg.add(var.set_sensor(sens))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if isinstance(config[CONF_THRESHOLD], float):
 | 
				
			||||||
 | 
					        cg.add(var.set_upper_threshold(config[CONF_THRESHOLD]))
 | 
				
			||||||
 | 
					        cg.add(var.set_lower_threshold(config[CONF_THRESHOLD]))
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        cg.add(var.set_upper_threshold(config[CONF_THRESHOLD][CONF_UPPER]))
 | 
				
			||||||
 | 
					        cg.add(var.set_lower_threshold(config[CONF_THRESHOLD][CONF_LOWER]))
 | 
				
			||||||
@@ -13,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
 | 
				
			|||||||
DEPENDENCIES = ["display"]
 | 
					DEPENDENCIES = ["display"]
 | 
				
			||||||
MULTI_CONF = True
 | 
					MULTI_CONF = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Animation_ = display.display_ns.class_("Animation")
 | 
					Animation_ = display.display_ns.class_("Animation", espImage.Image_)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ANIMATION_SCHEMA = cv.Schema(
 | 
					ANIMATION_SCHEMA = cv.Schema(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -44,8 +44,9 @@ async def to_code(config):
 | 
				
			|||||||
    width, height = image.size
 | 
					    width, height = image.size
 | 
				
			||||||
    frames = image.n_frames
 | 
					    frames = image.n_frames
 | 
				
			||||||
    if CONF_RESIZE in config:
 | 
					    if CONF_RESIZE in config:
 | 
				
			||||||
        image.thumbnail(config[CONF_RESIZE])
 | 
					        new_width_max, new_height_max = config[CONF_RESIZE]
 | 
				
			||||||
        width, height = image.size
 | 
					        ratio = min(new_width_max / width, new_height_max / height)
 | 
				
			||||||
 | 
					        width, height = int(width * ratio), int(height * ratio)
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        if width > 500 or height > 500:
 | 
					        if width > 500 or height > 500:
 | 
				
			||||||
            _LOGGER.warning(
 | 
					            _LOGGER.warning(
 | 
				
			||||||
@@ -59,7 +60,13 @@ async def to_code(config):
 | 
				
			|||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
            frame = image.convert("L", dither=Image.NONE)
 | 
					            frame = image.convert("L", dither=Image.NONE)
 | 
				
			||||||
 | 
					            if CONF_RESIZE in config:
 | 
				
			||||||
 | 
					                frame = frame.resize([width, height])
 | 
				
			||||||
            pixels = list(frame.getdata())
 | 
					            pixels = list(frame.getdata())
 | 
				
			||||||
 | 
					            if len(pixels) != height * width:
 | 
				
			||||||
 | 
					                raise core.EsphomeError(
 | 
				
			||||||
 | 
					                    f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
            for pix in pixels:
 | 
					            for pix in pixels:
 | 
				
			||||||
                data[pos] = pix
 | 
					                data[pos] = pix
 | 
				
			||||||
                pos += 1
 | 
					                pos += 1
 | 
				
			||||||
@@ -69,8 +76,16 @@ async def to_code(config):
 | 
				
			|||||||
        pos = 0
 | 
					        pos = 0
 | 
				
			||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
 | 
					            if CONF_RESIZE in config:
 | 
				
			||||||
 | 
					                image.thumbnail(config[CONF_RESIZE])
 | 
				
			||||||
            frame = image.convert("RGB")
 | 
					            frame = image.convert("RGB")
 | 
				
			||||||
 | 
					            if CONF_RESIZE in config:
 | 
				
			||||||
 | 
					                frame = frame.resize([width, height])
 | 
				
			||||||
            pixels = list(frame.getdata())
 | 
					            pixels = list(frame.getdata())
 | 
				
			||||||
 | 
					            if len(pixels) != height * width:
 | 
				
			||||||
 | 
					                raise core.EsphomeError(
 | 
				
			||||||
 | 
					                    f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
            for pix in pixels:
 | 
					            for pix in pixels:
 | 
				
			||||||
                data[pos] = pix[0]
 | 
					                data[pos] = pix[0]
 | 
				
			||||||
                pos += 1
 | 
					                pos += 1
 | 
				
			||||||
@@ -79,12 +94,37 @@ async def to_code(config):
 | 
				
			|||||||
                data[pos] = pix[2]
 | 
					                data[pos] = pix[2]
 | 
				
			||||||
                pos += 1
 | 
					                pos += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif config[CONF_TYPE] == "RGB565":
 | 
				
			||||||
 | 
					        data = [0 for _ in range(height * width * 2 * frames)]
 | 
				
			||||||
 | 
					        pos = 0
 | 
				
			||||||
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
 | 
					            frame = image.convert("RGB")
 | 
				
			||||||
 | 
					            if CONF_RESIZE in config:
 | 
				
			||||||
 | 
					                frame = frame.resize([width, height])
 | 
				
			||||||
 | 
					            pixels = list(frame.getdata())
 | 
				
			||||||
 | 
					            if len(pixels) != height * width:
 | 
				
			||||||
 | 
					                raise core.EsphomeError(
 | 
				
			||||||
 | 
					                    f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            for pix in pixels:
 | 
				
			||||||
 | 
					                R = pix[0] >> 3
 | 
				
			||||||
 | 
					                G = pix[1] >> 2
 | 
				
			||||||
 | 
					                B = pix[2] >> 3
 | 
				
			||||||
 | 
					                rgb = (R << 11) | (G << 5) | B
 | 
				
			||||||
 | 
					                data[pos] = rgb >> 8
 | 
				
			||||||
 | 
					                pos += 1
 | 
				
			||||||
 | 
					                data[pos] = rgb & 255
 | 
				
			||||||
 | 
					                pos += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    elif config[CONF_TYPE] == "BINARY":
 | 
					    elif config[CONF_TYPE] == "BINARY":
 | 
				
			||||||
        width8 = ((width + 7) // 8) * 8
 | 
					        width8 = ((width + 7) // 8) * 8
 | 
				
			||||||
        data = [0 for _ in range((height * width8 // 8) * frames)]
 | 
					        data = [0 for _ in range((height * width8 // 8) * frames)]
 | 
				
			||||||
        for frameIndex in range(frames):
 | 
					        for frameIndex in range(frames):
 | 
				
			||||||
            image.seek(frameIndex)
 | 
					            image.seek(frameIndex)
 | 
				
			||||||
            frame = image.convert("1", dither=Image.NONE)
 | 
					            frame = image.convert("1", dither=Image.NONE)
 | 
				
			||||||
 | 
					            if CONF_RESIZE in config:
 | 
				
			||||||
 | 
					                frame = frame.resize([width, height])
 | 
				
			||||||
            for y in range(height):
 | 
					            for y in range(height):
 | 
				
			||||||
                for x in range(width):
 | 
					                for x in range(width):
 | 
				
			||||||
                    if frame.getpixel((x, y)):
 | 
					                    if frame.getpixel((x, y)):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,17 +34,21 @@ void Anova::control(const ClimateCall &call) {
 | 
				
			|||||||
        ESP_LOGW(TAG, "Unsupported mode: %d", mode);
 | 
					        ESP_LOGW(TAG, "Unsupported mode: %d", mode);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
					    auto status =
 | 
				
			||||||
                                           pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
    if (status)
 | 
					                                 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (call.get_target_temperature().has_value()) {
 | 
					  if (call.get_target_temperature().has_value()) {
 | 
				
			||||||
    auto pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
 | 
					    auto *pkt = this->codec_->get_set_target_temp_request(*call.get_target_temperature());
 | 
				
			||||||
    auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
					    auto status =
 | 
				
			||||||
                                           pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
    if (status)
 | 
					                                 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,7 +61,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
				
			|||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
					    case ESP_GATTC_SEARCH_CMPL_EVT: {
 | 
				
			||||||
      auto chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
 | 
					      auto *chr = this->parent_->get_characteristic(ANOVA_SERVICE_UUID, ANOVA_CHARACTERISTIC_UUID);
 | 
				
			||||||
      if (chr == nullptr) {
 | 
					      if (chr == nullptr) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
 | 
					        ESP_LOGW(TAG, "[%s] No control service found at device, not an Anova..?", this->get_name().c_str());
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
 | 
					        ESP_LOGW(TAG, "[%s] Note, this component does not currently support Anova Nano.", this->get_name().c_str());
 | 
				
			||||||
@@ -65,7 +69,8 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      this->char_handle_ = chr->handle;
 | 
					      this->char_handle_ = chr->handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      auto status = esp_ble_gattc_register_for_notify(this->parent_->gattc_if, this->parent_->remote_bda, chr->handle);
 | 
					      auto status = esp_ble_gattc_register_for_notify(this->parent_->get_gattc_if(), this->parent_->get_remote_bda(),
 | 
				
			||||||
 | 
					                                                      chr->handle);
 | 
				
			||||||
      if (status) {
 | 
					      if (status) {
 | 
				
			||||||
        ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
 | 
					        ESP_LOGW(TAG, "[%s] esp_ble_gattc_register_for_notify failed, status=%d", this->get_name().c_str(), status);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -92,7 +97,7 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      if (this->codec_->has_unit()) {
 | 
					      if (this->codec_->has_unit()) {
 | 
				
			||||||
        this->fahrenheit_ = (this->codec_->unit_ == 'f');
 | 
					        this->fahrenheit_ = (this->codec_->unit_ == 'f');
 | 
				
			||||||
        ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celcius");
 | 
					        ESP_LOGD(TAG, "Anova units is %s", this->fahrenheit_ ? "fahrenheit" : "celsius");
 | 
				
			||||||
        this->current_request_++;
 | 
					        this->current_request_++;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      this->publish_state();
 | 
					      this->publish_state();
 | 
				
			||||||
@@ -112,11 +117,12 @@ void Anova::gattc_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (pkt != nullptr) {
 | 
					        if (pkt != nullptr) {
 | 
				
			||||||
          auto status =
 | 
					          auto status =
 | 
				
			||||||
              esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_, pkt->length,
 | 
					              esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
                                       pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					                                       pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
          if (status)
 | 
					          if (status) {
 | 
				
			||||||
            ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
 | 
					            ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(),
 | 
				
			||||||
                     status);
 | 
					                     status);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
@@ -133,13 +139,15 @@ void Anova::update() {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (this->current_request_ < 2) {
 | 
					  if (this->current_request_ < 2) {
 | 
				
			||||||
    auto pkt = this->codec_->get_read_device_status_request();
 | 
					    auto *pkt = this->codec_->get_read_device_status_request();
 | 
				
			||||||
    if (this->current_request_ == 0)
 | 
					    if (this->current_request_ == 0)
 | 
				
			||||||
      this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
 | 
					      this->codec_->get_set_unit_request(this->fahrenheit_ ? 'f' : 'c');
 | 
				
			||||||
    auto status = esp_ble_gattc_write_char(this->parent_->gattc_if, this->parent_->conn_id, this->char_handle_,
 | 
					    auto status =
 | 
				
			||||||
                                           pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
					        esp_ble_gattc_write_char(this->parent_->get_gattc_if(), this->parent_->get_conn_id(), this->char_handle_,
 | 
				
			||||||
    if (status)
 | 
					                                 pkt->length, pkt->data, ESP_GATT_WRITE_TYPE_NO_RSP, ESP_GATT_AUTH_REQ_NONE);
 | 
				
			||||||
 | 
					    if (status) {
 | 
				
			||||||
      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
					      ESP_LOGW(TAG, "[%s] esp_ble_gattc_write_char failed, status=%d", this->parent_->address_str().c_str(), status);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    this->current_request_++;
 | 
					    this->current_request_++;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,13 +30,13 @@ class Anova : public climate::Climate, public esphome::ble_client::BLEClientNode
 | 
				
			|||||||
  climate::ClimateTraits traits() override {
 | 
					  climate::ClimateTraits traits() override {
 | 
				
			||||||
    auto traits = climate::ClimateTraits();
 | 
					    auto traits = climate::ClimateTraits();
 | 
				
			||||||
    traits.set_supports_current_temperature(true);
 | 
					    traits.set_supports_current_temperature(true);
 | 
				
			||||||
    traits.set_supports_heat_mode(true);
 | 
					    traits.set_supported_modes({climate::CLIMATE_MODE_OFF, climate::ClimateMode::CLIMATE_MODE_HEAT});
 | 
				
			||||||
    traits.set_visual_min_temperature(25.0);
 | 
					    traits.set_visual_min_temperature(25.0);
 | 
				
			||||||
    traits.set_visual_max_temperature(100.0);
 | 
					    traits.set_visual_max_temperature(100.0);
 | 
				
			||||||
    traits.set_visual_temperature_step(0.1);
 | 
					    traits.set_visual_temperature_step(0.1);
 | 
				
			||||||
    return traits;
 | 
					    return traits;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void set_unit_of_measurement(const char *);
 | 
					  void set_unit_of_measurement(const char *unit);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  std::unique_ptr<AnovaCodec> codec_;
 | 
					  std::unique_ptr<AnovaCodec> codec_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,51 +73,46 @@ AnovaPacket *AnovaCodec::get_stop_request() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
					void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
				
			||||||
  memset(this->buf_, 0, 32);
 | 
					  char buf[32];
 | 
				
			||||||
  strncpy(this->buf_, (char *) data, length);
 | 
					  memset(buf, 0, sizeof(buf));
 | 
				
			||||||
 | 
					  strncpy(buf, (char *) data, std::min<uint16_t>(length, sizeof(buf) - 1));
 | 
				
			||||||
  this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
 | 
					  this->has_target_temp_ = this->has_current_temp_ = this->has_unit_ = this->has_running_ = false;
 | 
				
			||||||
  switch (this->current_query_) {
 | 
					  switch (this->current_query_) {
 | 
				
			||||||
    case READ_DEVICE_STATUS: {
 | 
					    case READ_DEVICE_STATUS: {
 | 
				
			||||||
      if (!strncmp(this->buf_, "stopped", 7)) {
 | 
					      if (!strncmp(buf, "stopped", 7)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = false;
 | 
					        this->running_ = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      if (!strncmp(this->buf_, "running", 7)) {
 | 
					      if (!strncmp(buf, "running", 7)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = true;
 | 
					        this->running_ = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case START: {
 | 
					    case START: {
 | 
				
			||||||
      if (!strncmp(this->buf_, "start", 5)) {
 | 
					      if (!strncmp(buf, "start", 5)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = true;
 | 
					        this->running_ = true;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case STOP: {
 | 
					    case STOP: {
 | 
				
			||||||
      if (!strncmp(this->buf_, "stop", 4)) {
 | 
					      if (!strncmp(buf, "stop", 4)) {
 | 
				
			||||||
        this->has_running_ = true;
 | 
					        this->has_running_ = true;
 | 
				
			||||||
        this->running_ = false;
 | 
					        this->running_ = false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case READ_TARGET_TEMPERATURE: {
 | 
					    case READ_TARGET_TEMPERATURE:
 | 
				
			||||||
      this->target_temp_ = parse_number<float>(this->buf_, sizeof(this->buf_)).value_or(0.0f);
 | 
					 | 
				
			||||||
      if (this->fahrenheit_)
 | 
					 | 
				
			||||||
        this->target_temp_ = ftoc(this->target_temp_);
 | 
					 | 
				
			||||||
      this->has_target_temp_ = true;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    case SET_TARGET_TEMPERATURE: {
 | 
					    case SET_TARGET_TEMPERATURE: {
 | 
				
			||||||
      this->target_temp_ = parse_number<float>(this->buf_, sizeof(this->buf_)).value_or(0.0f);
 | 
					      this->target_temp_ = parse_number<float>(str_until(buf, '\r')).value_or(0.0f);
 | 
				
			||||||
      if (this->fahrenheit_)
 | 
					      if (this->fahrenheit_)
 | 
				
			||||||
        this->target_temp_ = ftoc(this->target_temp_);
 | 
					        this->target_temp_ = ftoc(this->target_temp_);
 | 
				
			||||||
      this->has_target_temp_ = true;
 | 
					      this->has_target_temp_ = true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case READ_CURRENT_TEMPERATURE: {
 | 
					    case READ_CURRENT_TEMPERATURE: {
 | 
				
			||||||
      this->current_temp_ = parse_number<float>(this->buf_, sizeof(this->buf_)).value_or(0.0f);
 | 
					      this->current_temp_ = parse_number<float>(str_until(buf, '\r')).value_or(0.0f);
 | 
				
			||||||
      if (this->fahrenheit_)
 | 
					      if (this->fahrenheit_)
 | 
				
			||||||
        this->current_temp_ = ftoc(this->current_temp_);
 | 
					        this->current_temp_ = ftoc(this->current_temp_);
 | 
				
			||||||
      this->has_current_temp_ = true;
 | 
					      this->has_current_temp_ = true;
 | 
				
			||||||
@@ -125,8 +120,8 @@ void AnovaCodec::decode(const uint8_t *data, uint16_t length) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    case SET_UNIT:
 | 
					    case SET_UNIT:
 | 
				
			||||||
    case READ_UNIT: {
 | 
					    case READ_UNIT: {
 | 
				
			||||||
      this->unit_ = this->buf_[0];
 | 
					      this->unit_ = buf[0];
 | 
				
			||||||
      this->fahrenheit_ = this->buf_[0] == 'f';
 | 
					      this->fahrenheit_ = buf[0] == 'f';
 | 
				
			||||||
      this->has_unit_ = true;
 | 
					      this->has_unit_ = true;
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -70,7 +70,6 @@ class AnovaCodec {
 | 
				
			|||||||
  bool has_current_temp_;
 | 
					  bool has_current_temp_;
 | 
				
			||||||
  bool has_unit_;
 | 
					  bool has_unit_;
 | 
				
			||||||
  bool has_running_;
 | 
					  bool has_running_;
 | 
				
			||||||
  char buf_[32];
 | 
					 | 
				
			||||||
  bool fahrenheit_;
 | 
					  bool fahrenheit_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  CurrentQuery current_query_;
 | 
					  CurrentQuery current_query_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,27 @@ AUTO_LOAD = ["sensor", "binary_sensor"]
 | 
				
			|||||||
MULTI_CONF = True
 | 
					MULTI_CONF = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONF_APDS9960_ID = "apds9960_id"
 | 
					CONF_APDS9960_ID = "apds9960_id"
 | 
				
			||||||
 | 
					CONF_LED_DRIVE = "led_drive"
 | 
				
			||||||
 | 
					CONF_PROXIMITY_GAIN = "proximity_gain"
 | 
				
			||||||
 | 
					CONF_AMBIENT_LIGHT_GAIN = "ambient_light_gain"
 | 
				
			||||||
 | 
					CONF_GESTURE_LED_DRIVE = "gesture_led_drive"
 | 
				
			||||||
 | 
					CONF_GESTURE_GAIN = "gesture_gain"
 | 
				
			||||||
 | 
					CONF_GESTURE_WAIT_TIME = "gesture_wait_time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DRIVE_LEVELS = {"100ma": 0, "50ma": 1, "25ma": 2, "12.5ma": 3}
 | 
				
			||||||
 | 
					PROXIMITY_LEVELS = {"1x": 0, "2x": 1, "4x": 2, "8x": 3}
 | 
				
			||||||
 | 
					AMBIENT_LEVELS = {"1x": 0, "4x": 1, "16x": 2, "64x": 3}
 | 
				
			||||||
 | 
					GESTURE_LEVELS = {"1x": 0, "2x": 1, "4x": 2, "8x": 3}
 | 
				
			||||||
 | 
					GESTURE_WAIT_TIMES = {
 | 
				
			||||||
 | 
					    "0ms": 0,
 | 
				
			||||||
 | 
					    "2.8ms": 1,
 | 
				
			||||||
 | 
					    "5.6ms": 2,
 | 
				
			||||||
 | 
					    "8.4ms": 3,
 | 
				
			||||||
 | 
					    "14ms": 4,
 | 
				
			||||||
 | 
					    "22.4ms": 5,
 | 
				
			||||||
 | 
					    "30.8ms": 6,
 | 
				
			||||||
 | 
					    "39.2ms": 7,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
apds9960_nds = cg.esphome_ns.namespace("apds9960")
 | 
					apds9960_nds = cg.esphome_ns.namespace("apds9960")
 | 
				
			||||||
APDS9960 = apds9960_nds.class_("APDS9960", cg.PollingComponent, i2c.I2CDevice)
 | 
					APDS9960 = apds9960_nds.class_("APDS9960", cg.PollingComponent, i2c.I2CDevice)
 | 
				
			||||||
@@ -16,6 +37,20 @@ CONFIG_SCHEMA = (
 | 
				
			|||||||
    cv.Schema(
 | 
					    cv.Schema(
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            cv.GenerateID(): cv.declare_id(APDS9960),
 | 
					            cv.GenerateID(): cv.declare_id(APDS9960),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_LED_DRIVE, "100mA"): cv.enum(DRIVE_LEVELS, lower=True),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_PROXIMITY_GAIN, "4x"): cv.enum(
 | 
				
			||||||
 | 
					                PROXIMITY_LEVELS, lower=True
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_AMBIENT_LIGHT_GAIN, "4x"): cv.enum(
 | 
				
			||||||
 | 
					                AMBIENT_LEVELS, lower=True
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_GESTURE_LED_DRIVE, "100mA"): cv.enum(
 | 
				
			||||||
 | 
					                DRIVE_LEVELS, lower=True
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_GESTURE_GAIN, "4x"): cv.enum(GESTURE_LEVELS, lower=True),
 | 
				
			||||||
 | 
					            cv.Optional(CONF_GESTURE_WAIT_TIME, "2.8ms"): cv.enum(
 | 
				
			||||||
 | 
					                GESTURE_WAIT_TIMES, lower=True
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    .extend(cv.polling_component_schema("60s"))
 | 
					    .extend(cv.polling_component_schema("60s"))
 | 
				
			||||||
@@ -27,3 +62,9 @@ async def to_code(config):
 | 
				
			|||||||
    var = cg.new_Pvariable(config[CONF_ID])
 | 
					    var = cg.new_Pvariable(config[CONF_ID])
 | 
				
			||||||
    await cg.register_component(var, config)
 | 
					    await cg.register_component(var, config)
 | 
				
			||||||
    await i2c.register_i2c_device(var, config)
 | 
					    await i2c.register_i2c_device(var, config)
 | 
				
			||||||
 | 
					    cg.add(var.set_led_drive(config[CONF_LED_DRIVE]))
 | 
				
			||||||
 | 
					    cg.add(var.set_proximity_gain(config[CONF_PROXIMITY_GAIN]))
 | 
				
			||||||
 | 
					    cg.add(var.set_ambient_gain(config[CONF_AMBIENT_LIGHT_GAIN]))
 | 
				
			||||||
 | 
					    cg.add(var.set_gesture_led_drive(config[CONF_GESTURE_LED_DRIVE]))
 | 
				
			||||||
 | 
					    cg.add(var.set_gesture_gain(config[CONF_GESTURE_GAIN]))
 | 
				
			||||||
 | 
					    cg.add(var.set_gesture_wait_time(config[CONF_GESTURE_WAIT_TIME]))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -46,16 +46,16 @@ void APDS9960::setup() {
 | 
				
			|||||||
  uint8_t val = 0;
 | 
					  uint8_t val = 0;
 | 
				
			||||||
  APDS9960_ERROR_CHECK(this->read_byte(0x8F, &val));
 | 
					  APDS9960_ERROR_CHECK(this->read_byte(0x8F, &val));
 | 
				
			||||||
  val &= 0b00111111;
 | 
					  val &= 0b00111111;
 | 
				
			||||||
  uint8_t led_drive = 0;  // led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
 | 
					  // led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
 | 
				
			||||||
  val |= (led_drive & 0b11) << 6;
 | 
					  val |= (this->led_drive_ & 0b11) << 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val &= 0b11110011;
 | 
					  val &= 0b11110011;
 | 
				
			||||||
  uint8_t proximity_gain = 2;  // proximity gain, 0 -> 1x, 1 -> 2X, 2 -> 4X, 4 -> 8X
 | 
					  // proximity gain, 0 -> 1x, 1 -> 2X, 2 -> 4X, 3 -> 8X
 | 
				
			||||||
  val |= (proximity_gain & 0b11) << 2;
 | 
					  val |= (this->proximity_gain_ & 0b11) << 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val &= 0b11111100;
 | 
					  val &= 0b11111100;
 | 
				
			||||||
  uint8_t ambient_gain = 1;  // ambient light gain, 0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x
 | 
					  // ambient light gain, 0 -> 1x, 1 -> 4x, 2 -> 16x, 3 -> 64x
 | 
				
			||||||
  val |= (ambient_gain & 0b11) << 0;
 | 
					  val |= (this->ambient_gain_ & 0b11) << 0;
 | 
				
			||||||
  APDS9960_WRITE_BYTE(0x8F, val);
 | 
					  APDS9960_WRITE_BYTE(0x8F, val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Pers (0x8C) -> 0x11 (2 consecutive proximity or ALS for interrupt)
 | 
					  // Pers (0x8C) -> 0x11 (2 consecutive proximity or ALS for interrupt)
 | 
				
			||||||
@@ -75,19 +75,18 @@ void APDS9960::setup() {
 | 
				
			|||||||
  // GConf 2 (0xA3, gesture config 2) ->
 | 
					  // GConf 2 (0xA3, gesture config 2) ->
 | 
				
			||||||
  APDS9960_ERROR_CHECK(this->read_byte(0xA3, &val));
 | 
					  APDS9960_ERROR_CHECK(this->read_byte(0xA3, &val));
 | 
				
			||||||
  val &= 0b10011111;
 | 
					  val &= 0b10011111;
 | 
				
			||||||
  uint8_t gesture_gain = 2;  // gesture gain, 0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x
 | 
					  // gesture gain, 0 -> 1x, 1 -> 2x, 2 -> 4x, 3 -> 8x
 | 
				
			||||||
  val |= (gesture_gain & 0b11) << 5;
 | 
					  val |= (this->gesture_gain_ & 0b11) << 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val &= 0b11100111;
 | 
					  val &= 0b11100111;
 | 
				
			||||||
  uint8_t gesture_led_drive = 0;  // gesture led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
 | 
					  // gesture led drive, 0 -> 100mA, 1 -> 50mA, 2 -> 25mA, 3 -> 12.5mA
 | 
				
			||||||
  val |= (gesture_led_drive & 0b11) << 3;
 | 
					  val |= (this->gesture_led_drive_ & 0b11) << 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val &= 0b11111000;
 | 
					  val &= 0b11111000;
 | 
				
			||||||
  // gesture wait time
 | 
					  // gesture wait time
 | 
				
			||||||
  // 0 -> 0ms, 1 -> 2.8ms, 2 -> 5.6ms, 3 -> 8.4ms
 | 
					  // 0 -> 0ms, 1 -> 2.8ms, 2 -> 5.6ms, 3 -> 8.4ms
 | 
				
			||||||
  // 4 -> 14.0ms, 5 -> 22.4 ms, 6 -> 30.8ms, 7 -> 39.2 ms
 | 
					  // 4 -> 14.0ms, 5 -> 22.4 ms, 6 -> 30.8ms, 7 -> 39.2 ms
 | 
				
			||||||
  uint8_t gesture_wait_time = 1;  // gesture wait time
 | 
					  val |= (this->gesture_wait_time_ & 0b111) << 0;
 | 
				
			||||||
  val |= (gesture_wait_time & 0b111) << 0;
 | 
					 | 
				
			||||||
  APDS9960_WRITE_BYTE(0xA3, val);
 | 
					  APDS9960_WRITE_BYTE(0xA3, val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // GOffsetU (0xA4) -> 0x00 (no offset)
 | 
					  // GOffsetU (0xA4) -> 0x00 (no offset)
 | 
				
			||||||
@@ -225,9 +224,10 @@ void APDS9960::read_gesture_data_() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  uint8_t fifo_level;
 | 
					  uint8_t fifo_level;
 | 
				
			||||||
  APDS9960_WARNING_CHECK(this->read_byte(0xAE, &fifo_level), "Reading FIFO level failed.");
 | 
					  APDS9960_WARNING_CHECK(this->read_byte(0xAE, &fifo_level), "Reading FIFO level failed.");
 | 
				
			||||||
  if (fifo_level == 0)
 | 
					  if (fifo_level == 0) {
 | 
				
			||||||
    // no data to process
 | 
					    // no data to process
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  APDS9960_WARNING_CHECK(fifo_level <= 32, "FIFO level has invalid value.")
 | 
					  APDS9960_WARNING_CHECK(fifo_level <= 32, "FIFO level has invalid value.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,6 +16,13 @@ class APDS9960 : public PollingComponent, public i2c::I2CDevice {
 | 
				
			|||||||
  void update() override;
 | 
					  void update() override;
 | 
				
			||||||
  void loop() override;
 | 
					  void loop() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void set_led_drive(uint8_t level) { this->led_drive_ = level; }
 | 
				
			||||||
 | 
					  void set_proximity_gain(uint8_t gain) { this->proximity_gain_ = gain; }
 | 
				
			||||||
 | 
					  void set_ambient_gain(uint8_t gain) { this->ambient_gain_ = gain; }
 | 
				
			||||||
 | 
					  void set_gesture_led_drive(uint8_t level) { this->gesture_led_drive_ = level; }
 | 
				
			||||||
 | 
					  void set_gesture_gain(uint8_t gain) { this->gesture_gain_ = gain; }
 | 
				
			||||||
 | 
					  void set_gesture_wait_time(uint8_t wait_time) { this->gesture_wait_time_ = wait_time; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  void set_red_channel(sensor::Sensor *red_channel) { red_channel_ = red_channel; }
 | 
					  void set_red_channel(sensor::Sensor *red_channel) { red_channel_ = red_channel; }
 | 
				
			||||||
  void set_green_channel(sensor::Sensor *green_channel) { green_channel_ = green_channel; }
 | 
					  void set_green_channel(sensor::Sensor *green_channel) { green_channel_ = green_channel; }
 | 
				
			||||||
  void set_blue_channel(sensor::Sensor *blue_channel) { blue_channel_ = blue_channel; }
 | 
					  void set_blue_channel(sensor::Sensor *blue_channel) { blue_channel_ = blue_channel; }
 | 
				
			||||||
@@ -36,6 +43,13 @@ class APDS9960 : public PollingComponent, public i2c::I2CDevice {
 | 
				
			|||||||
  void report_gesture_(int gesture);
 | 
					  void report_gesture_(int gesture);
 | 
				
			||||||
  void process_dataset_(int up, int down, int left, int right);
 | 
					  void process_dataset_(int up, int down, int left, int right);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint8_t led_drive_;
 | 
				
			||||||
 | 
					  uint8_t proximity_gain_;
 | 
				
			||||||
 | 
					  uint8_t ambient_gain_;
 | 
				
			||||||
 | 
					  uint8_t gesture_led_drive_;
 | 
				
			||||||
 | 
					  uint8_t gesture_gain_;
 | 
				
			||||||
 | 
					  uint8_t gesture_wait_time_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  sensor::Sensor *red_channel_{nullptr};
 | 
					  sensor::Sensor *red_channel_{nullptr};
 | 
				
			||||||
  sensor::Sensor *green_channel_{nullptr};
 | 
					  sensor::Sensor *green_channel_{nullptr};
 | 
				
			||||||
  sensor::Sensor *blue_channel_{nullptr};
 | 
					  sensor::Sensor *blue_channel_{nullptr};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import esphome.codegen as cg
 | 
					import esphome.codegen as cg
 | 
				
			||||||
import esphome.config_validation as cv
 | 
					import esphome.config_validation as cv
 | 
				
			||||||
from esphome.components import binary_sensor
 | 
					from esphome.components import binary_sensor
 | 
				
			||||||
from esphome.const import CONF_DIRECTION, CONF_DEVICE_CLASS, DEVICE_CLASS_MOVING
 | 
					from esphome.const import CONF_DIRECTION, DEVICE_CLASS_MOVING
 | 
				
			||||||
from . import APDS9960, CONF_APDS9960_ID
 | 
					from . import APDS9960, CONF_APDS9960_ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DEPENDENCIES = ["apds9960"]
 | 
					DEPENDENCIES = ["apds9960"]
 | 
				
			||||||
@@ -13,13 +13,12 @@ DIRECTIONS = {
 | 
				
			|||||||
    "RIGHT": "set_right_direction",
 | 
					    "RIGHT": "set_right_direction",
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend(
 | 
					CONFIG_SCHEMA = binary_sensor.binary_sensor_schema(
 | 
				
			||||||
 | 
					    device_class=DEVICE_CLASS_MOVING
 | 
				
			||||||
 | 
					).extend(
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True),
 | 
					 | 
				
			||||||
        cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960),
 | 
					        cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960),
 | 
				
			||||||
        cv.Optional(
 | 
					        cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True),
 | 
				
			||||||
            CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING
 | 
					 | 
				
			||||||
        ): binary_sensor.device_class,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -40,6 +40,19 @@ service APIConnection {
 | 
				
			|||||||
  rpc climate_command (ClimateCommandRequest) returns (void) {}
 | 
					  rpc climate_command (ClimateCommandRequest) returns (void) {}
 | 
				
			||||||
  rpc number_command (NumberCommandRequest) returns (void) {}
 | 
					  rpc number_command (NumberCommandRequest) returns (void) {}
 | 
				
			||||||
  rpc select_command (SelectCommandRequest) returns (void) {}
 | 
					  rpc select_command (SelectCommandRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc button_command (ButtonCommandRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc lock_command (LockCommandRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc media_player_command (MediaPlayerCommandRequest) returns (void) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  rpc subscribe_bluetooth_le_advertisements(SubscribeBluetoothLEAdvertisementsRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_device_request(BluetoothDeviceRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_get_services(BluetoothGATTGetServicesRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_read(BluetoothGATTReadRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_write(BluetoothGATTWriteRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_read_descriptor(BluetoothGATTReadDescriptorRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_write_descriptor(BluetoothGATTWriteDescriptorRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc bluetooth_gatt_notify(BluetoothGATTNotifyRequest) returns (void) {}
 | 
				
			||||||
 | 
					  rpc subscribe_bluetooth_connections_free(SubscribeBluetoothConnectionsFreeRequest) returns (BluetoothConnectionsFreeResponse) {}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,6 +87,8 @@ message HelloRequest {
 | 
				
			|||||||
  // Not strictly necessary to send but nice for debugging
 | 
					  // Not strictly necessary to send but nice for debugging
 | 
				
			||||||
  // purposes.
 | 
					  // purposes.
 | 
				
			||||||
  string client_info = 1;
 | 
					  string client_info = 1;
 | 
				
			||||||
 | 
					  uint32 api_version_major = 2;
 | 
				
			||||||
 | 
					  uint32 api_version_minor = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Confirmation of successful connection request.
 | 
					// Confirmation of successful connection request.
 | 
				
			||||||
@@ -94,6 +109,9 @@ message HelloResponse {
 | 
				
			|||||||
  // and only exists for debugging/logging purposes.
 | 
					  // and only exists for debugging/logging purposes.
 | 
				
			||||||
  // For example "ESPHome v1.10.0 on ESP8266"
 | 
					  // For example "ESPHome v1.10.0 on ESP8266"
 | 
				
			||||||
  string server_info = 3;
 | 
					  string server_info = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // The name of the server (App.get_name())
 | 
				
			||||||
 | 
					  string name = 4;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Message sent at the beginning of each connection to authenticate the client
 | 
					// Message sent at the beginning of each connection to authenticate the client
 | 
				
			||||||
@@ -184,6 +202,10 @@ message DeviceInfoResponse {
 | 
				
			|||||||
  string project_version = 9;
 | 
					  string project_version = 9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  uint32 webserver_port = 10;
 | 
					  uint32 webserver_port = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32 bluetooth_proxy_version = 11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string manufacturer = 12;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
message ListEntitiesRequest {
 | 
					message ListEntitiesRequest {
 | 
				
			||||||
@@ -467,6 +489,7 @@ enum SensorStateClass {
 | 
				
			|||||||
  STATE_CLASS_NONE = 0;
 | 
					  STATE_CLASS_NONE = 0;
 | 
				
			||||||
  STATE_CLASS_MEASUREMENT = 1;
 | 
					  STATE_CLASS_MEASUREMENT = 1;
 | 
				
			||||||
  STATE_CLASS_TOTAL_INCREASING = 2;
 | 
					  STATE_CLASS_TOTAL_INCREASING = 2;
 | 
				
			||||||
 | 
					  STATE_CLASS_TOTAL = 3;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum SensorLastResetType {
 | 
					enum SensorLastResetType {
 | 
				
			||||||
@@ -524,6 +547,7 @@ message ListEntitiesSwitchResponse {
 | 
				
			|||||||
  bool assumed_state = 6;
 | 
					  bool assumed_state = 6;
 | 
				
			||||||
  bool disabled_by_default = 7;
 | 
					  bool disabled_by_default = 7;
 | 
				
			||||||
  EntityCategory entity_category = 8;
 | 
					  EntityCategory entity_category = 8;
 | 
				
			||||||
 | 
					  string device_class = 9;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message SwitchStateResponse {
 | 
					message SwitchStateResponse {
 | 
				
			||||||
  option (id) = 26;
 | 
					  option (id) = 26;
 | 
				
			||||||
@@ -868,6 +892,11 @@ message ClimateCommandRequest {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ==================== NUMBER ====================
 | 
					// ==================== NUMBER ====================
 | 
				
			||||||
 | 
					enum NumberMode {
 | 
				
			||||||
 | 
					  NUMBER_MODE_AUTO = 0;
 | 
				
			||||||
 | 
					  NUMBER_MODE_BOX = 1;
 | 
				
			||||||
 | 
					  NUMBER_MODE_SLIDER = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
message ListEntitiesNumberResponse {
 | 
					message ListEntitiesNumberResponse {
 | 
				
			||||||
  option (id) = 49;
 | 
					  option (id) = 49;
 | 
				
			||||||
  option (source) = SOURCE_SERVER;
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
@@ -884,6 +913,9 @@ message ListEntitiesNumberResponse {
 | 
				
			|||||||
  float step = 8;
 | 
					  float step = 8;
 | 
				
			||||||
  bool disabled_by_default = 9;
 | 
					  bool disabled_by_default = 9;
 | 
				
			||||||
  EntityCategory entity_category = 10;
 | 
					  EntityCategory entity_category = 10;
 | 
				
			||||||
 | 
					  string unit_of_measurement = 11;
 | 
				
			||||||
 | 
					  NumberMode mode = 12;
 | 
				
			||||||
 | 
					  string device_class = 13;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
message NumberStateResponse {
 | 
					message NumberStateResponse {
 | 
				
			||||||
  option (id) = 50;
 | 
					  option (id) = 50;
 | 
				
			||||||
@@ -944,3 +976,362 @@ message SelectCommandRequest {
 | 
				
			|||||||
  fixed32 key = 1;
 | 
					  fixed32 key = 1;
 | 
				
			||||||
  string state = 2;
 | 
					  string state = 2;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ==================== LOCK ====================
 | 
				
			||||||
 | 
					enum LockState {
 | 
				
			||||||
 | 
					  LOCK_STATE_NONE = 0;
 | 
				
			||||||
 | 
					  LOCK_STATE_LOCKED = 1;
 | 
				
			||||||
 | 
					  LOCK_STATE_UNLOCKED = 2;
 | 
				
			||||||
 | 
					  LOCK_STATE_JAMMED = 3;
 | 
				
			||||||
 | 
					  LOCK_STATE_LOCKING = 4;
 | 
				
			||||||
 | 
					  LOCK_STATE_UNLOCKING = 5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					enum LockCommand  {
 | 
				
			||||||
 | 
					  LOCK_UNLOCK = 0;
 | 
				
			||||||
 | 
					  LOCK_LOCK = 1;
 | 
				
			||||||
 | 
					  LOCK_OPEN = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message ListEntitiesLockResponse {
 | 
				
			||||||
 | 
					  option (id) = 58;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_LOCK";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string object_id = 1;
 | 
				
			||||||
 | 
					  fixed32 key = 2;
 | 
				
			||||||
 | 
					  string name = 3;
 | 
				
			||||||
 | 
					  string unique_id = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string icon = 5;
 | 
				
			||||||
 | 
					  bool disabled_by_default = 6;
 | 
				
			||||||
 | 
					  EntityCategory entity_category = 7;
 | 
				
			||||||
 | 
					  bool assumed_state = 8;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool supports_open = 9;
 | 
				
			||||||
 | 
					  bool requires_code = 10;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Not yet implemented:
 | 
				
			||||||
 | 
					  string code_format = 11;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message LockStateResponse {
 | 
				
			||||||
 | 
					  option (id) = 59;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_LOCK";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					  fixed32 key = 1;
 | 
				
			||||||
 | 
					  LockState state = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message LockCommandRequest {
 | 
				
			||||||
 | 
					  option (id) = 60;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_LOCK";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					  fixed32 key = 1;
 | 
				
			||||||
 | 
					  LockCommand command = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  // Not yet implemented:
 | 
				
			||||||
 | 
					  bool has_code = 3;
 | 
				
			||||||
 | 
					  string code = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ==================== BUTTON ====================
 | 
				
			||||||
 | 
					message ListEntitiesButtonResponse {
 | 
				
			||||||
 | 
					  option (id) = 61;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BUTTON";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string object_id = 1;
 | 
				
			||||||
 | 
					  fixed32 key = 2;
 | 
				
			||||||
 | 
					  string name = 3;
 | 
				
			||||||
 | 
					  string unique_id = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string icon = 5;
 | 
				
			||||||
 | 
					  bool disabled_by_default = 6;
 | 
				
			||||||
 | 
					  EntityCategory entity_category = 7;
 | 
				
			||||||
 | 
					  string device_class = 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message ButtonCommandRequest {
 | 
				
			||||||
 | 
					  option (id) = 62;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BUTTON";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fixed32 key = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ==================== MEDIA PLAYER ====================
 | 
				
			||||||
 | 
					enum MediaPlayerState {
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_NONE = 0;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_IDLE = 1;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_PLAYING = 2;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_PAUSED = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					enum MediaPlayerCommand {
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_PLAY = 0;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_PAUSE = 1;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_STOP = 2;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_MUTE = 3;
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_UNMUTE = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message ListEntitiesMediaPlayerResponse {
 | 
				
			||||||
 | 
					  option (id) = 63;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_MEDIA_PLAYER";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string object_id = 1;
 | 
				
			||||||
 | 
					  fixed32 key = 2;
 | 
				
			||||||
 | 
					  string name = 3;
 | 
				
			||||||
 | 
					  string unique_id = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  string icon = 5;
 | 
				
			||||||
 | 
					  bool disabled_by_default = 6;
 | 
				
			||||||
 | 
					  EntityCategory entity_category = 7;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool supports_pause = 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message MediaPlayerStateResponse {
 | 
				
			||||||
 | 
					  option (id) = 64;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_MEDIA_PLAYER";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					  fixed32 key = 1;
 | 
				
			||||||
 | 
					  MediaPlayerState state = 2;
 | 
				
			||||||
 | 
					  float volume = 3;
 | 
				
			||||||
 | 
					  bool muted = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message MediaPlayerCommandRequest {
 | 
				
			||||||
 | 
					  option (id) = 65;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_MEDIA_PLAYER";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fixed32 key = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool has_command = 2;
 | 
				
			||||||
 | 
					  MediaPlayerCommand command = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool has_volume = 4;
 | 
				
			||||||
 | 
					  float volume = 5;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bool has_media_url = 6;
 | 
				
			||||||
 | 
					  string media_url = 7;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ==================== BLUETOOTH ====================
 | 
				
			||||||
 | 
					message SubscribeBluetoothLEAdvertisementsRequest {
 | 
				
			||||||
 | 
					  option (id) = 66;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothServiceData {
 | 
				
			||||||
 | 
					  string uuid = 1;
 | 
				
			||||||
 | 
					  repeated uint32 legacy_data = 2 [deprecated = true];
 | 
				
			||||||
 | 
					  bytes data = 3; // Changed in proto version 1.7
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					message BluetoothLEAdvertisementResponse {
 | 
				
			||||||
 | 
					  option (id) = 67;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					  option (no_delay) = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  string name = 2;
 | 
				
			||||||
 | 
					  sint32 rssi = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  repeated string service_uuids = 4;
 | 
				
			||||||
 | 
					  repeated BluetoothServiceData service_data = 5;
 | 
				
			||||||
 | 
					  repeated BluetoothServiceData manufacturer_data = 6;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32 address_type = 7;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum BluetoothDeviceRequestType {
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0;
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1;
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2;
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3;
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4;
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothDeviceRequest {
 | 
				
			||||||
 | 
					  option (id) = 68;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  BluetoothDeviceRequestType request_type = 2;
 | 
				
			||||||
 | 
					  bool has_address_type = 3;
 | 
				
			||||||
 | 
					  uint32 address_type = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothDeviceConnectionResponse {
 | 
				
			||||||
 | 
					  option (id) = 69;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  bool connected = 2;
 | 
				
			||||||
 | 
					  uint32 mtu = 3;
 | 
				
			||||||
 | 
					  int32 error = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTGetServicesRequest {
 | 
				
			||||||
 | 
					  option (id) = 70;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTDescriptor {
 | 
				
			||||||
 | 
					  repeated uint64 uuid = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTCharacteristic {
 | 
				
			||||||
 | 
					  repeated uint64 uuid = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					  uint32 properties = 3;
 | 
				
			||||||
 | 
					  repeated BluetoothGATTDescriptor descriptors = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTService {
 | 
				
			||||||
 | 
					  repeated uint64 uuid = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					  repeated BluetoothGATTCharacteristic characteristics = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTGetServicesResponse {
 | 
				
			||||||
 | 
					  option (id) = 71;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  repeated BluetoothGATTService services = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTGetServicesDoneResponse {
 | 
				
			||||||
 | 
					  option (id) = 72;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTReadRequest {
 | 
				
			||||||
 | 
					  option (id) = 73;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTReadResponse {
 | 
				
			||||||
 | 
					  option (id) = 74;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bytes data = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTWriteRequest {
 | 
				
			||||||
 | 
					  option (id) = 75;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					  bool response = 3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bytes data = 4;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTReadDescriptorRequest {
 | 
				
			||||||
 | 
					  option (id) = 76;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTWriteDescriptorRequest {
 | 
				
			||||||
 | 
					  option (id) = 77;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bytes data = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTNotifyRequest {
 | 
				
			||||||
 | 
					  option (id) = 78;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					  bool enable = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTNotifyDataResponse {
 | 
				
			||||||
 | 
					  option (id) = 79;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bytes data = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message SubscribeBluetoothConnectionsFreeRequest {
 | 
				
			||||||
 | 
					  option (id) = 80;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_CLIENT;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothConnectionsFreeResponse {
 | 
				
			||||||
 | 
					  option (id) = 81;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint32 free = 1;
 | 
				
			||||||
 | 
					  uint32 limit = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTErrorResponse {
 | 
				
			||||||
 | 
					  option (id) = 82;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					  int32 error = 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTWriteResponse {
 | 
				
			||||||
 | 
					  option (id) = 83;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					message BluetoothGATTNotifyResponse {
 | 
				
			||||||
 | 
					  option (id) = 84;
 | 
				
			||||||
 | 
					  option (source) = SOURCE_SERVER;
 | 
				
			||||||
 | 
					  option (ifdef) = "USE_BLUETOOTH_PROXY";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  uint64 address = 1;
 | 
				
			||||||
 | 
					  uint32 handle = 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
#include "api_connection.h"
 | 
					#include "api_connection.h"
 | 
				
			||||||
#include "esphome/core/entity_base.h"
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					 | 
				
			||||||
#include "esphome/components/network/util.h"
 | 
					 | 
				
			||||||
#include "esphome/core/version.h"
 | 
					 | 
				
			||||||
#include "esphome/core/hal.h"
 | 
					 | 
				
			||||||
#include <cerrno>
 | 
					#include <cerrno>
 | 
				
			||||||
 | 
					#include "esphome/components/network/util.h"
 | 
				
			||||||
 | 
					#include "esphome/core/entity_base.h"
 | 
				
			||||||
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					#include "esphome/core/version.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_DEEP_SLEEP
 | 
					#ifdef USE_DEEP_SLEEP
 | 
				
			||||||
#include "esphome/components/deep_sleep/deep_sleep_component.h"
 | 
					#include "esphome/components/deep_sleep/deep_sleep_component.h"
 | 
				
			||||||
@@ -12,17 +12,18 @@
 | 
				
			|||||||
#ifdef USE_HOMEASSISTANT_TIME
 | 
					#ifdef USE_HOMEASSISTANT_TIME
 | 
				
			||||||
#include "esphome/components/homeassistant/time/homeassistant_time.h"
 | 
					#include "esphome/components/homeassistant/time/homeassistant_time.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
#include "esphome/components/fan/fan_helpers.h"
 | 
					#include "esphome/components/bluetooth_proxy/bluetooth_proxy.h"
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char *const TAG = "api.connection";
 | 
					static const char *const TAG = "api.connection";
 | 
				
			||||||
 | 
					static const int ESP32_CAMERA_STOP_STREAM = 5000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
 | 
					APIConnection::APIConnection(std::unique_ptr<socket::Socket> sock, APIServer *parent)
 | 
				
			||||||
    : parent_(parent), initial_state_iterator_(parent, this), list_entities_iterator_(parent, this) {
 | 
					    : parent_(parent), initial_state_iterator_(this), list_entities_iterator_(this) {
 | 
				
			||||||
  this->proto_write_buffer_.reserve(64);
 | 
					  this->proto_write_buffer_.reserve(64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(USE_API_PLAINTEXT)
 | 
					#if defined(USE_API_PLAINTEXT)
 | 
				
			||||||
@@ -104,6 +105,7 @@ void APIConnection::loop() {
 | 
				
			|||||||
      ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_info_.c_str());
 | 
					      ESP_LOGW(TAG, "%s didn't respond to ping request in time. Disconnecting...", this->client_info_.c_str());
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else if (now - this->last_traffic_ > keepalive) {
 | 
					  } else if (now - this->last_traffic_ > keepalive) {
 | 
				
			||||||
 | 
					    ESP_LOGVV(TAG, "Sending keepalive PING...");
 | 
				
			||||||
    this->sent_ping_ = true;
 | 
					    this->sent_ping_ = true;
 | 
				
			||||||
    this->send_ping_request(PingRequest());
 | 
					    this->send_ping_request(PingRequest());
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -132,7 +134,7 @@ void APIConnection::loop() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  if (state_subs_at_ != -1) {
 | 
					  if (state_subs_at_ != -1) {
 | 
				
			||||||
    const auto &subs = this->parent_->get_state_subs();
 | 
					    const auto &subs = this->parent_->get_state_subs();
 | 
				
			||||||
    if (state_subs_at_ >= subs.size()) {
 | 
					    if (state_subs_at_ >= (int) subs.size()) {
 | 
				
			||||||
      state_subs_at_ = -1;
 | 
					      state_subs_at_ = -1;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      auto &it = subs[state_subs_at_];
 | 
					      auto &it = subs[state_subs_at_];
 | 
				
			||||||
@@ -251,10 +253,7 @@ void APIConnection::cover_command(const CoverCommandRequest &msg) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
// Shut-up about usage of deprecated speed_level_to_enum/speed_enum_to_level functions for a bit.
 | 
					bool APIConnection::send_fan_state(fan::Fan *fan) {
 | 
				
			||||||
#pragma GCC diagnostic push
 | 
					 | 
				
			||||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
 | 
					 | 
				
			||||||
bool APIConnection::send_fan_state(fan::FanState *fan) {
 | 
					 | 
				
			||||||
  if (!this->state_subscription_)
 | 
					  if (!this->state_subscription_)
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -266,13 +265,12 @@ bool APIConnection::send_fan_state(fan::FanState *fan) {
 | 
				
			|||||||
    resp.oscillating = fan->oscillating;
 | 
					    resp.oscillating = fan->oscillating;
 | 
				
			||||||
  if (traits.supports_speed()) {
 | 
					  if (traits.supports_speed()) {
 | 
				
			||||||
    resp.speed_level = fan->speed;
 | 
					    resp.speed_level = fan->speed;
 | 
				
			||||||
    resp.speed = static_cast<enums::FanSpeed>(fan::speed_level_to_enum(fan->speed, traits.supported_speed_count()));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (traits.supports_direction())
 | 
					  if (traits.supports_direction())
 | 
				
			||||||
    resp.direction = static_cast<enums::FanDirection>(fan->direction);
 | 
					    resp.direction = static_cast<enums::FanDirection>(fan->direction);
 | 
				
			||||||
  return this->send_fan_state_response(resp);
 | 
					  return this->send_fan_state_response(resp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
bool APIConnection::send_fan_info(fan::FanState *fan) {
 | 
					bool APIConnection::send_fan_info(fan::Fan *fan) {
 | 
				
			||||||
  auto traits = fan->get_traits();
 | 
					  auto traits = fan->get_traits();
 | 
				
			||||||
  ListEntitiesFanResponse msg;
 | 
					  ListEntitiesFanResponse msg;
 | 
				
			||||||
  msg.key = fan->get_object_id_hash();
 | 
					  msg.key = fan->get_object_id_hash();
 | 
				
			||||||
@@ -289,12 +287,10 @@ bool APIConnection::send_fan_info(fan::FanState *fan) {
 | 
				
			|||||||
  return this->send_list_entities_fan_response(msg);
 | 
					  return this->send_list_entities_fan_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
					void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
				
			||||||
  fan::FanState *fan = App.get_fan_by_key(msg.key);
 | 
					  fan::Fan *fan = App.get_fan_by_key(msg.key);
 | 
				
			||||||
  if (fan == nullptr)
 | 
					  if (fan == nullptr)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  auto traits = fan->get_traits();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  auto call = fan->make_call();
 | 
					  auto call = fan->make_call();
 | 
				
			||||||
  if (msg.has_state)
 | 
					  if (msg.has_state)
 | 
				
			||||||
    call.set_state(msg.state);
 | 
					    call.set_state(msg.state);
 | 
				
			||||||
@@ -303,14 +299,11 @@ void APIConnection::fan_command(const FanCommandRequest &msg) {
 | 
				
			|||||||
  if (msg.has_speed_level) {
 | 
					  if (msg.has_speed_level) {
 | 
				
			||||||
    // Prefer level
 | 
					    // Prefer level
 | 
				
			||||||
    call.set_speed(msg.speed_level);
 | 
					    call.set_speed(msg.speed_level);
 | 
				
			||||||
  } else if (msg.has_speed) {
 | 
					 | 
				
			||||||
    call.set_speed(fan::speed_enum_to_level(static_cast<fan::FanSpeed>(msg.speed), traits.supported_speed_count()));
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (msg.has_direction)
 | 
					  if (msg.has_direction)
 | 
				
			||||||
    call.set_direction(static_cast<fan::FanDirection>(msg.direction));
 | 
					    call.set_direction(static_cast<fan::FanDirection>(msg.direction));
 | 
				
			||||||
  call.perform();
 | 
					  call.perform();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#pragma GCC diagnostic pop
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
@@ -461,6 +454,7 @@ bool APIConnection::send_switch_info(switch_::Switch *a_switch) {
 | 
				
			|||||||
  msg.assumed_state = a_switch->assumed_state();
 | 
					  msg.assumed_state = a_switch->assumed_state();
 | 
				
			||||||
  msg.disabled_by_default = a_switch->is_disabled_by_default();
 | 
					  msg.disabled_by_default = a_switch->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
 | 
					  msg.entity_category = static_cast<enums::EntityCategory>(a_switch->get_entity_category());
 | 
				
			||||||
 | 
					  msg.device_class = a_switch->get_device_class();
 | 
				
			||||||
  return this->send_list_entities_switch_response(msg);
 | 
					  return this->send_list_entities_switch_response(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
					void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
				
			||||||
@@ -468,10 +462,11 @@ void APIConnection::switch_command(const SwitchCommandRequest &msg) {
 | 
				
			|||||||
  if (a_switch == nullptr)
 | 
					  if (a_switch == nullptr)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (msg.state)
 | 
					  if (msg.state) {
 | 
				
			||||||
    a_switch->turn_on();
 | 
					    a_switch->turn_on();
 | 
				
			||||||
  else
 | 
					  } else {
 | 
				
			||||||
    a_switch->turn_off();
 | 
					    a_switch->turn_off();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -619,6 +614,9 @@ bool APIConnection::send_number_info(number::Number *number) {
 | 
				
			|||||||
  msg.icon = number->get_icon();
 | 
					  msg.icon = number->get_icon();
 | 
				
			||||||
  msg.disabled_by_default = number->is_disabled_by_default();
 | 
					  msg.disabled_by_default = number->is_disabled_by_default();
 | 
				
			||||||
  msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
 | 
					  msg.entity_category = static_cast<enums::EntityCategory>(number->get_entity_category());
 | 
				
			||||||
 | 
					  msg.unit_of_measurement = number->traits.get_unit_of_measurement();
 | 
				
			||||||
 | 
					  msg.mode = static_cast<enums::NumberMode>(number->traits.get_mode());
 | 
				
			||||||
 | 
					  msg.device_class = number->traits.get_device_class();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  msg.min_value = number->traits.get_min_value();
 | 
					  msg.min_value = number->traits.get_min_value();
 | 
				
			||||||
  msg.max_value = number->traits.get_max_value();
 | 
					  msg.max_value = number->traits.get_max_value();
 | 
				
			||||||
@@ -674,13 +672,126 @@ void APIConnection::select_command(const SelectCommandRequest &msg) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					bool APIConnection::send_button_info(button::Button *button) {
 | 
				
			||||||
 | 
					  ListEntitiesButtonResponse msg;
 | 
				
			||||||
 | 
					  msg.key = button->get_object_id_hash();
 | 
				
			||||||
 | 
					  msg.object_id = button->get_object_id();
 | 
				
			||||||
 | 
					  msg.name = button->get_name();
 | 
				
			||||||
 | 
					  msg.unique_id = get_default_unique_id("button", button);
 | 
				
			||||||
 | 
					  msg.icon = button->get_icon();
 | 
				
			||||||
 | 
					  msg.disabled_by_default = button->is_disabled_by_default();
 | 
				
			||||||
 | 
					  msg.entity_category = static_cast<enums::EntityCategory>(button->get_entity_category());
 | 
				
			||||||
 | 
					  msg.device_class = button->get_device_class();
 | 
				
			||||||
 | 
					  return this->send_list_entities_button_response(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::button_command(const ButtonCommandRequest &msg) {
 | 
				
			||||||
 | 
					  button::Button *button = App.get_button_by_key(msg.key);
 | 
				
			||||||
 | 
					  if (button == nullptr)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  button->press();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					bool APIConnection::send_lock_state(lock::Lock *a_lock, lock::LockState state) {
 | 
				
			||||||
 | 
					  if (!this->state_subscription_)
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  LockStateResponse resp{};
 | 
				
			||||||
 | 
					  resp.key = a_lock->get_object_id_hash();
 | 
				
			||||||
 | 
					  resp.state = static_cast<enums::LockState>(state);
 | 
				
			||||||
 | 
					  return this->send_lock_state_response(resp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					bool APIConnection::send_lock_info(lock::Lock *a_lock) {
 | 
				
			||||||
 | 
					  ListEntitiesLockResponse msg;
 | 
				
			||||||
 | 
					  msg.key = a_lock->get_object_id_hash();
 | 
				
			||||||
 | 
					  msg.object_id = a_lock->get_object_id();
 | 
				
			||||||
 | 
					  msg.name = a_lock->get_name();
 | 
				
			||||||
 | 
					  msg.unique_id = get_default_unique_id("lock", a_lock);
 | 
				
			||||||
 | 
					  msg.icon = a_lock->get_icon();
 | 
				
			||||||
 | 
					  msg.assumed_state = a_lock->traits.get_assumed_state();
 | 
				
			||||||
 | 
					  msg.disabled_by_default = a_lock->is_disabled_by_default();
 | 
				
			||||||
 | 
					  msg.entity_category = static_cast<enums::EntityCategory>(a_lock->get_entity_category());
 | 
				
			||||||
 | 
					  msg.supports_open = a_lock->traits.get_supports_open();
 | 
				
			||||||
 | 
					  msg.requires_code = a_lock->traits.get_requires_code();
 | 
				
			||||||
 | 
					  return this->send_list_entities_lock_response(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::lock_command(const LockCommandRequest &msg) {
 | 
				
			||||||
 | 
					  lock::Lock *a_lock = App.get_lock_by_key(msg.key);
 | 
				
			||||||
 | 
					  if (a_lock == nullptr)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (msg.command) {
 | 
				
			||||||
 | 
					    case enums::LOCK_UNLOCK:
 | 
				
			||||||
 | 
					      a_lock->unlock();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case enums::LOCK_LOCK:
 | 
				
			||||||
 | 
					      a_lock->lock();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case enums::LOCK_OPEN:
 | 
				
			||||||
 | 
					      a_lock->open();
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_player) {
 | 
				
			||||||
 | 
					  if (!this->state_subscription_)
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  MediaPlayerStateResponse resp{};
 | 
				
			||||||
 | 
					  resp.key = media_player->get_object_id_hash();
 | 
				
			||||||
 | 
					  resp.state = static_cast<enums::MediaPlayerState>(media_player->state);
 | 
				
			||||||
 | 
					  resp.volume = media_player->volume;
 | 
				
			||||||
 | 
					  resp.muted = media_player->is_muted();
 | 
				
			||||||
 | 
					  return this->send_media_player_state_response(resp);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					bool APIConnection::send_media_player_info(media_player::MediaPlayer *media_player) {
 | 
				
			||||||
 | 
					  ListEntitiesMediaPlayerResponse msg;
 | 
				
			||||||
 | 
					  msg.key = media_player->get_object_id_hash();
 | 
				
			||||||
 | 
					  msg.object_id = media_player->get_object_id();
 | 
				
			||||||
 | 
					  msg.name = media_player->get_name();
 | 
				
			||||||
 | 
					  msg.unique_id = get_default_unique_id("media_player", media_player);
 | 
				
			||||||
 | 
					  msg.icon = media_player->get_icon();
 | 
				
			||||||
 | 
					  msg.disabled_by_default = media_player->is_disabled_by_default();
 | 
				
			||||||
 | 
					  msg.entity_category = static_cast<enums::EntityCategory>(media_player->get_entity_category());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto traits = media_player->get_traits();
 | 
				
			||||||
 | 
					  msg.supports_pause = traits.get_supports_pause();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return this->send_list_entities_media_player_response(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
 | 
				
			||||||
 | 
					  media_player::MediaPlayer *media_player = App.get_media_player_by_key(msg.key);
 | 
				
			||||||
 | 
					  if (media_player == nullptr)
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  auto call = media_player->make_call();
 | 
				
			||||||
 | 
					  if (msg.has_command) {
 | 
				
			||||||
 | 
					    call.set_command(static_cast<media_player::MediaPlayerCommand>(msg.command));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (msg.has_volume) {
 | 
				
			||||||
 | 
					    call.set_volume(msg.volume);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (msg.has_media_url) {
 | 
				
			||||||
 | 
					    call.set_media_url(msg.media_url);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  call.perform();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_ESP32_CAMERA
 | 
					#ifdef USE_ESP32_CAMERA
 | 
				
			||||||
void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
 | 
					void APIConnection::send_camera_state(std::shared_ptr<esp32_camera::CameraImage> image) {
 | 
				
			||||||
  if (!this->state_subscription_)
 | 
					  if (!this->state_subscription_)
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  if (this->image_reader_.available())
 | 
					  if (this->image_reader_.available())
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  this->image_reader_.set_image(std::move(image));
 | 
					  if (image->was_requested_by(esphome::esp32_camera::API_REQUESTER) ||
 | 
				
			||||||
 | 
					      image->was_requested_by(esphome::esp32_camera::IDLE))
 | 
				
			||||||
 | 
					    this->image_reader_.set_image(std::move(image));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
 | 
					bool APIConnection::send_camera_info(esp32_camera::ESP32Camera *camera) {
 | 
				
			||||||
  ListEntitiesCameraResponse msg;
 | 
					  ListEntitiesCameraResponse msg;
 | 
				
			||||||
@@ -698,9 +809,14 @@ void APIConnection::camera_image(const CameraImageRequest &msg) {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (msg.single)
 | 
					  if (msg.single)
 | 
				
			||||||
    esp32_camera::global_esp32_camera->request_image();
 | 
					    esp32_camera::global_esp32_camera->request_image(esphome::esp32_camera::API_REQUESTER);
 | 
				
			||||||
  if (msg.stream)
 | 
					  if (msg.stream) {
 | 
				
			||||||
    esp32_camera::global_esp32_camera->request_stream();
 | 
					    esp32_camera::global_esp32_camera->start_stream(esphome::esp32_camera::API_REQUESTER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    App.scheduler.set_timeout(this->parent_, "api_esp32_camera_stop_stream", ESP32_CAMERA_STOP_STREAM, []() {
 | 
				
			||||||
 | 
					      esp32_camera::global_esp32_camera->stop_stream(esphome::esp32_camera::API_REQUESTER);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -711,6 +827,56 @@ void APIConnection::on_get_time_response(const GetTimeResponse &value) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIConnection::send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg) {
 | 
				
			||||||
 | 
					  if (!this->bluetooth_le_advertisement_subscription_)
 | 
				
			||||||
 | 
					    return false;
 | 
				
			||||||
 | 
					  if (this->client_api_version_major_ < 1 || this->client_api_version_minor_ < 7) {
 | 
				
			||||||
 | 
					    BluetoothLEAdvertisementResponse resp = msg;
 | 
				
			||||||
 | 
					    for (auto &service : resp.service_data) {
 | 
				
			||||||
 | 
					      service.legacy_data.assign(service.data.begin(), service.data.end());
 | 
				
			||||||
 | 
					      service.data.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    for (auto &manufacturer_data : resp.manufacturer_data) {
 | 
				
			||||||
 | 
					      manufacturer_data.legacy_data.assign(manufacturer_data.data.begin(), manufacturer_data.data.end());
 | 
				
			||||||
 | 
					      manufacturer_data.data.clear();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return this->send_bluetooth_le_advertisement_response(resp);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return this->send_bluetooth_le_advertisement_response(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_device_request(const BluetoothDeviceRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_device_request(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_read_descriptor(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_write_descriptor(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_send_services(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void APIConnection::bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) {
 | 
				
			||||||
 | 
					  bluetooth_proxy::global_bluetooth_proxy->bluetooth_gatt_notify(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BluetoothConnectionsFreeResponse APIConnection::subscribe_bluetooth_connections_free(
 | 
				
			||||||
 | 
					    const SubscribeBluetoothConnectionsFreeRequest &msg) {
 | 
				
			||||||
 | 
					  BluetoothConnectionsFreeResponse resp;
 | 
				
			||||||
 | 
					  resp.free = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_free();
 | 
				
			||||||
 | 
					  resp.limit = bluetooth_proxy::global_bluetooth_proxy->get_bluetooth_connections_limit();
 | 
				
			||||||
 | 
					  return resp;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool APIConnection::send_log_message(int level, const char *tag, const char *line) {
 | 
					bool APIConnection::send_log_message(int level, const char *tag, const char *line) {
 | 
				
			||||||
  if (this->log_subscription_ < level)
 | 
					  if (this->log_subscription_ < level)
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
@@ -728,12 +894,17 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin
 | 
				
			|||||||
HelloResponse APIConnection::hello(const HelloRequest &msg) {
 | 
					HelloResponse APIConnection::hello(const HelloRequest &msg) {
 | 
				
			||||||
  this->client_info_ = msg.client_info + " (" + this->helper_->getpeername() + ")";
 | 
					  this->client_info_ = msg.client_info + " (" + this->helper_->getpeername() + ")";
 | 
				
			||||||
  this->helper_->set_log_info(client_info_);
 | 
					  this->helper_->set_log_info(client_info_);
 | 
				
			||||||
  ESP_LOGV(TAG, "Hello from client: '%s'", this->client_info_.c_str());
 | 
					  this->client_api_version_major_ = msg.api_version_major;
 | 
				
			||||||
 | 
					  this->client_api_version_minor_ = msg.api_version_minor;
 | 
				
			||||||
 | 
					  ESP_LOGV(TAG, "Hello from client: '%s' | API Version %d.%d", this->client_info_.c_str(),
 | 
				
			||||||
 | 
					           this->client_api_version_major_, this->client_api_version_minor_);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  HelloResponse resp;
 | 
					  HelloResponse resp;
 | 
				
			||||||
  resp.api_version_major = 1;
 | 
					  resp.api_version_major = 1;
 | 
				
			||||||
  resp.api_version_minor = 6;
 | 
					  resp.api_version_minor = 7;
 | 
				
			||||||
  resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
 | 
					  resp.server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
 | 
				
			||||||
 | 
					  resp.name = App.get_name();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  this->connection_state_ = ConnectionState::CONNECTED;
 | 
					  this->connection_state_ = ConnectionState::CONNECTED;
 | 
				
			||||||
  return resp;
 | 
					  return resp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -762,6 +933,11 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
 | 
				
			|||||||
  resp.mac_address = get_mac_address_pretty();
 | 
					  resp.mac_address = get_mac_address_pretty();
 | 
				
			||||||
  resp.esphome_version = ESPHOME_VERSION;
 | 
					  resp.esphome_version = ESPHOME_VERSION;
 | 
				
			||||||
  resp.compilation_time = App.get_compilation_time();
 | 
					  resp.compilation_time = App.get_compilation_time();
 | 
				
			||||||
 | 
					#if defined(USE_ESP8266) || defined(USE_ESP32)
 | 
				
			||||||
 | 
					  resp.manufacturer = "Espressif";
 | 
				
			||||||
 | 
					#elif defined(USE_RP2040)
 | 
				
			||||||
 | 
					  resp.manufacturer = "Raspberry Pi";
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  resp.model = ESPHOME_BOARD;
 | 
					  resp.model = ESPHOME_BOARD;
 | 
				
			||||||
#ifdef USE_DEEP_SLEEP
 | 
					#ifdef USE_DEEP_SLEEP
 | 
				
			||||||
  resp.has_deep_sleep = deep_sleep::global_has_deep_sleep;
 | 
					  resp.has_deep_sleep = deep_sleep::global_has_deep_sleep;
 | 
				
			||||||
@@ -771,15 +947,19 @@ DeviceInfoResponse APIConnection::device_info(const DeviceInfoRequest &msg) {
 | 
				
			|||||||
  resp.project_version = ESPHOME_PROJECT_VERSION;
 | 
					  resp.project_version = ESPHOME_PROJECT_VERSION;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_WEBSERVER
 | 
					#ifdef USE_WEBSERVER
 | 
				
			||||||
  resp.webserver_port = WEBSERVER_PORT;
 | 
					  resp.webserver_port = USE_WEBSERVER_PORT;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  resp.bluetooth_proxy_version = bluetooth_proxy::global_bluetooth_proxy->has_active() ? 3 : 1;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  return resp;
 | 
					  return resp;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) {
 | 
					void APIConnection::on_home_assistant_state_response(const HomeAssistantStateResponse &msg) {
 | 
				
			||||||
  for (auto &it : this->parent_->get_state_subs())
 | 
					  for (auto &it : this->parent_->get_state_subs()) {
 | 
				
			||||||
    if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) {
 | 
					    if (it.entity_id == msg.entity_id && it.attribute.value() == msg.attribute) {
 | 
				
			||||||
      it.callback(msg.state);
 | 
					      it.callback(msg.state);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
 | 
					void APIConnection::execute_service(const ExecuteServiceRequest &msg) {
 | 
				
			||||||
  bool found = false;
 | 
					  bool found = false;
 | 
				
			||||||
@@ -828,7 +1008,7 @@ bool APIConnection::send_buffer(ProtoWriteBuffer buffer, uint32_t message_type)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return false;
 | 
					    return false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  this->last_traffic_ = millis();
 | 
					  // Do not set last_traffic_ on send
 | 
				
			||||||
  return true;
 | 
					  return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
void APIConnection::on_unauthenticated_access() {
 | 
					void APIConnection::on_unauthenticated_access() {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,13 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					#include "api_frame_helper.h"
 | 
				
			||||||
#include "esphome/core/application.h"
 | 
					 | 
				
			||||||
#include "api_pb2.h"
 | 
					#include "api_pb2.h"
 | 
				
			||||||
#include "api_pb2_service.h"
 | 
					#include "api_pb2_service.h"
 | 
				
			||||||
#include "api_server.h"
 | 
					#include "api_server.h"
 | 
				
			||||||
#include "api_frame_helper.h"
 | 
					#include "esphome/core/application.h"
 | 
				
			||||||
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
@@ -32,8 +34,8 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
  void cover_command(const CoverCommandRequest &msg) override;
 | 
					  void cover_command(const CoverCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
  bool send_fan_state(fan::FanState *fan);
 | 
					  bool send_fan_state(fan::Fan *fan);
 | 
				
			||||||
  bool send_fan_info(fan::FanState *fan);
 | 
					  bool send_fan_info(fan::Fan *fan);
 | 
				
			||||||
  void fan_command(const FanCommandRequest &msg) override;
 | 
					  void fan_command(const FanCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
@@ -73,6 +75,20 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
  bool send_select_state(select::Select *select, std::string state);
 | 
					  bool send_select_state(select::Select *select, std::string state);
 | 
				
			||||||
  bool send_select_info(select::Select *select);
 | 
					  bool send_select_info(select::Select *select);
 | 
				
			||||||
  void select_command(const SelectCommandRequest &msg) override;
 | 
					  void select_command(const SelectCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  bool send_button_info(button::Button *button);
 | 
				
			||||||
 | 
					  void button_command(const ButtonCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  bool send_lock_state(lock::Lock *a_lock, lock::LockState state);
 | 
				
			||||||
 | 
					  bool send_lock_info(lock::Lock *a_lock);
 | 
				
			||||||
 | 
					  void lock_command(const LockCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  bool send_media_player_state(media_player::MediaPlayer *media_player);
 | 
				
			||||||
 | 
					  bool send_media_player_info(media_player::MediaPlayer *media_player);
 | 
				
			||||||
 | 
					  void media_player_command(const MediaPlayerCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  bool send_log_message(int level, const char *tag, const char *line);
 | 
					  bool send_log_message(int level, const char *tag, const char *line);
 | 
				
			||||||
  void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
 | 
					  void send_homeassistant_service_call(const HomeassistantServiceResponse &call) {
 | 
				
			||||||
@@ -80,6 +96,20 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
    this->send_homeassistant_service_response(call);
 | 
					    this->send_homeassistant_service_response(call);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &msg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) override;
 | 
				
			||||||
 | 
					  void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) override;
 | 
				
			||||||
 | 
					  BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
 | 
				
			||||||
 | 
					      const SubscribeBluetoothConnectionsFreeRequest &msg) override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef USE_HOMEASSISTANT_TIME
 | 
					#ifdef USE_HOMEASSISTANT_TIME
 | 
				
			||||||
  void send_time_request() {
 | 
					  void send_time_request() {
 | 
				
			||||||
    GetTimeRequest req;
 | 
					    GetTimeRequest req;
 | 
				
			||||||
@@ -120,6 +150,9 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
    return {};
 | 
					    return {};
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void execute_service(const ExecuteServiceRequest &msg) override;
 | 
					  void execute_service(const ExecuteServiceRequest &msg) override;
 | 
				
			||||||
 | 
					  void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) override {
 | 
				
			||||||
 | 
					    this->bluetooth_le_advertisement_subscription_ = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; }
 | 
					  bool is_authenticated() override { return this->connection_state_ == ConnectionState::AUTHENTICATED; }
 | 
				
			||||||
  bool is_connection_setup() override {
 | 
					  bool is_connection_setup() override {
 | 
				
			||||||
    return this->connection_state_ == ConnectionState ::CONNECTED || this->is_authenticated();
 | 
					    return this->connection_state_ == ConnectionState ::CONNECTED || this->is_authenticated();
 | 
				
			||||||
@@ -153,6 +186,8 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
  std::unique_ptr<APIFrameHelper> helper_;
 | 
					  std::unique_ptr<APIFrameHelper> helper_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::string client_info_;
 | 
					  std::string client_info_;
 | 
				
			||||||
 | 
					  uint32_t client_api_version_major_{0};
 | 
				
			||||||
 | 
					  uint32_t client_api_version_minor_{0};
 | 
				
			||||||
#ifdef USE_ESP32_CAMERA
 | 
					#ifdef USE_ESP32_CAMERA
 | 
				
			||||||
  esp32_camera::CameraImageReader image_reader_;
 | 
					  esp32_camera::CameraImageReader image_reader_;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -162,6 +197,7 @@ class APIConnection : public APIServerConnection {
 | 
				
			|||||||
  uint32_t last_traffic_;
 | 
					  uint32_t last_traffic_;
 | 
				
			||||||
  bool sent_ping_{false};
 | 
					  bool sent_ping_{false};
 | 
				
			||||||
  bool service_call_subscription_{false};
 | 
					  bool service_call_subscription_{false};
 | 
				
			||||||
 | 
					  bool bluetooth_le_advertisement_subscription_{false};
 | 
				
			||||||
  bool next_close_ = false;
 | 
					  bool next_close_ = false;
 | 
				
			||||||
  APIServer *parent_;
 | 
					  APIServer *parent_;
 | 
				
			||||||
  InitialStateIterator initial_state_iterator_;
 | 
					  InitialStateIterator initial_state_iterator_;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
#include "api_frame_helper.h"
 | 
					#include "api_frame_helper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					#include "esphome/core/hal.h"
 | 
				
			||||||
#include "esphome/core/helpers.h"
 | 
					#include "esphome/core/helpers.h"
 | 
				
			||||||
 | 
					#include "esphome/core/application.h"
 | 
				
			||||||
#include "proto.h"
 | 
					#include "proto.h"
 | 
				
			||||||
#include <cstring>
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -174,9 +176,6 @@ APIError APINoiseFrameHelper::loop() {
 | 
				
			|||||||
 * errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase.
 | 
					 * errno API_ERROR_HANDSHAKE_PACKET_LEN: Packet too big for this phase.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
					APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (frame == nullptr) {
 | 
					  if (frame == nullptr) {
 | 
				
			||||||
    HELPER_LOG("Bad argument for try_read_frame_");
 | 
					    HELPER_LOG("Bad argument for try_read_frame_");
 | 
				
			||||||
    return APIError::BAD_ARG;
 | 
					    return APIError::BAD_ARG;
 | 
				
			||||||
@@ -200,7 +199,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_header_buf_len_ += received;
 | 
					    rx_header_buf_len_ += received;
 | 
				
			||||||
    if (received != to_read) {
 | 
					    if ((size_t) received != to_read) {
 | 
				
			||||||
      // not a full read
 | 
					      // not a full read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -247,7 +246,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_buf_len_ += received;
 | 
					    rx_buf_len_ += received;
 | 
				
			||||||
    if (received != to_read) {
 | 
					    if ((size_t) received != to_read) {
 | 
				
			||||||
      // not all read
 | 
					      // not all read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -255,7 +254,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // uncomment for even more debugging
 | 
					  // uncomment for even more debugging
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
  ESP_LOGVV(TAG, "Received frame: %s", hexencode(rx_buf_).c_str());
 | 
					  ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  frame->msg = std::move(rx_buf_);
 | 
					  frame->msg = std::move(rx_buf_);
 | 
				
			||||||
  // consume msg
 | 
					  // consume msg
 | 
				
			||||||
@@ -271,7 +270,7 @@ APIError APINoiseFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * If the handshake is still active when this method returns and a read/write can't take place at
 | 
					 * If the handshake is still active when this method returns and a read/write can't take place at
 | 
				
			||||||
 * the moment, returns WOULD_BLOCK.
 | 
					 * the moment, returns WOULD_BLOCK.
 | 
				
			||||||
 * If an error occured, returns that error. Only returns OK if the transport is ready for data
 | 
					 * If an error occurred, returns that error. Only returns OK if the transport is ready for data
 | 
				
			||||||
 * traffic.
 | 
					 * traffic.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
APIError APINoiseFrameHelper::state_action_() {
 | 
					APIError APINoiseFrameHelper::state_action_() {
 | 
				
			||||||
@@ -304,9 +303,16 @@ APIError APINoiseFrameHelper::state_action_() {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  if (state_ == State::SERVER_HELLO) {
 | 
					  if (state_ == State::SERVER_HELLO) {
 | 
				
			||||||
    // send server hello
 | 
					    // send server hello
 | 
				
			||||||
    uint8_t msg[1];
 | 
					    std::vector<uint8_t> msg;
 | 
				
			||||||
    msg[0] = 0x01;  // chosen proto
 | 
					    // chosen proto
 | 
				
			||||||
    aerr = write_frame_(msg, 1);
 | 
					    msg.push_back(0x01);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // node name, terminated by null byte
 | 
				
			||||||
 | 
					    const std::string &name = App.get_name();
 | 
				
			||||||
 | 
					    const uint8_t *name_ptr = reinterpret_cast<const uint8_t *>(name.c_str());
 | 
				
			||||||
 | 
					    msg.insert(msg.end(), name_ptr, name_ptr + name.size() + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    aerr = write_frame_(msg.data(), msg.size());
 | 
				
			||||||
    if (aerr != APIError::OK)
 | 
					    if (aerr != APIError::OK)
 | 
				
			||||||
      return aerr;
 | 
					      return aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -544,13 +550,13 @@ APIError APINoiseFrameHelper::try_send_tx_buf_() {
 | 
				
			|||||||
APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
					APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			||||||
  if (iovcnt == 0)
 | 
					  if (iovcnt == 0)
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t total_write_len = 0;
 | 
					  size_t total_write_len = 0;
 | 
				
			||||||
  for (int i = 0; i < iovcnt; i++) {
 | 
					  for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
    ESP_LOGVV(TAG, "Sending raw: %s", hexencode(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
					    ESP_LOGVV(TAG, "Sending raw: %s",
 | 
				
			||||||
 | 
					              format_hex_pretty(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    total_write_len += iov[i].iov_len;
 | 
					    total_write_len += iov[i].iov_len;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -580,11 +586,11 @@ APIError APINoiseFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
  } else if (sent == -1) {
 | 
					  } else if (sent == -1) {
 | 
				
			||||||
    // an error occured
 | 
					    // an error occurred
 | 
				
			||||||
    state_ = State::FAILED;
 | 
					    state_ = State::FAILED;
 | 
				
			||||||
    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
					    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
				
			||||||
    return APIError::SOCKET_WRITE_FAILED;
 | 
					    return APIError::SOCKET_WRITE_FAILED;
 | 
				
			||||||
  } else if (sent != total_write_len) {
 | 
					  } else if ((size_t) sent != total_write_len) {
 | 
				
			||||||
    // partially sent, add end to tx_buf
 | 
					    // partially sent, add end to tx_buf
 | 
				
			||||||
    size_t to_consume = sent;
 | 
					    size_t to_consume = sent;
 | 
				
			||||||
    for (int i = 0; i < iovcnt; i++) {
 | 
					    for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
@@ -724,7 +730,12 @@ APIError APINoiseFrameHelper::shutdown(int how) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
// declare how noise generates random bytes (here with a good HWRNG based on the RF system)
 | 
					// declare how noise generates random bytes (here with a good HWRNG based on the RF system)
 | 
				
			||||||
void noise_rand_bytes(void *output, size_t len) { esphome::fill_random(reinterpret_cast<uint8_t *>(output), len); }
 | 
					void noise_rand_bytes(void *output, size_t len) {
 | 
				
			||||||
 | 
					  if (!esphome::random_bytes(reinterpret_cast<uint8_t *>(output), len)) {
 | 
				
			||||||
 | 
					    ESP_LOGE(TAG, "Failed to acquire random bytes, rebooting!");
 | 
				
			||||||
 | 
					    arch_restart();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif  // USE_API_NOISE
 | 
					#endif  // USE_API_NOISE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -778,9 +789,6 @@ APIError APIPlaintextFrameHelper::loop() {
 | 
				
			|||||||
 * error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame.
 | 
					 * error API_ERROR_BAD_INDICATOR: Bad indicator byte at start of frame.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
					APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (frame == nullptr) {
 | 
					  if (frame == nullptr) {
 | 
				
			||||||
    HELPER_LOG("Bad argument for try_read_frame_");
 | 
					    HELPER_LOG("Bad argument for try_read_frame_");
 | 
				
			||||||
    return APIError::BAD_ARG;
 | 
					    return APIError::BAD_ARG;
 | 
				
			||||||
@@ -854,7 +862,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
      return APIError::CONNECTION_CLOSED;
 | 
					      return APIError::CONNECTION_CLOSED;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    rx_buf_len_ += received;
 | 
					    rx_buf_len_ += received;
 | 
				
			||||||
    if (received != to_read) {
 | 
					    if ((size_t) received != to_read) {
 | 
				
			||||||
      // not all read
 | 
					      // not all read
 | 
				
			||||||
      return APIError::WOULD_BLOCK;
 | 
					      return APIError::WOULD_BLOCK;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -862,7 +870,7 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  // uncomment for even more debugging
 | 
					  // uncomment for even more debugging
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
  ESP_LOGVV(TAG, "Received frame: %s", hexencode(rx_buf_).c_str());
 | 
					  ESP_LOGVV(TAG, "Received frame: %s", format_hex_pretty(rx_buf_).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  frame->msg = std::move(rx_buf_);
 | 
					  frame->msg = std::move(rx_buf_);
 | 
				
			||||||
  // consume msg
 | 
					  // consume msg
 | 
				
			||||||
@@ -874,7 +882,6 @@ APIError APIPlaintextFrameHelper::try_read_frame_(ParsedFrame *frame) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
					APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (state_ != State::DATA) {
 | 
					  if (state_ != State::DATA) {
 | 
				
			||||||
@@ -894,9 +901,6 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
bool APIPlaintextFrameHelper::can_write_without_blocking() { return state_ == State::DATA && tx_buf_.empty(); }
 | 
					bool APIPlaintextFrameHelper::can_write_without_blocking() { return state_ == State::DATA && tx_buf_.empty(); }
 | 
				
			||||||
APIError APIPlaintextFrameHelper::write_packet(uint16_t type, const uint8_t *payload, size_t payload_len) {
 | 
					APIError APIPlaintextFrameHelper::write_packet(uint16_t type, const uint8_t *payload, size_t payload_len) {
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (state_ != State::DATA) {
 | 
					  if (state_ != State::DATA) {
 | 
				
			||||||
    return APIError::BAD_STATE;
 | 
					    return APIError::BAD_STATE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -940,13 +944,13 @@ APIError APIPlaintextFrameHelper::try_send_tx_buf_() {
 | 
				
			|||||||
APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
					APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt) {
 | 
				
			||||||
  if (iovcnt == 0)
 | 
					  if (iovcnt == 0)
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
  int err;
 | 
					 | 
				
			||||||
  APIError aerr;
 | 
					  APIError aerr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  size_t total_write_len = 0;
 | 
					  size_t total_write_len = 0;
 | 
				
			||||||
  for (int i = 0; i < iovcnt; i++) {
 | 
					  for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
#ifdef HELPER_LOG_PACKETS
 | 
					#ifdef HELPER_LOG_PACKETS
 | 
				
			||||||
    ESP_LOGVV(TAG, "Sending raw: %s", hexencode(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
					    ESP_LOGVV(TAG, "Sending raw: %s",
 | 
				
			||||||
 | 
					              format_hex_pretty(reinterpret_cast<uint8_t *>(iov[i].iov_base), iov[i].iov_len).c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    total_write_len += iov[i].iov_len;
 | 
					    total_write_len += iov[i].iov_len;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -976,11 +980,11 @@ APIError APIPlaintextFrameHelper::write_raw_(const struct iovec *iov, int iovcnt
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return APIError::OK;
 | 
					    return APIError::OK;
 | 
				
			||||||
  } else if (sent == -1) {
 | 
					  } else if (sent == -1) {
 | 
				
			||||||
    // an error occured
 | 
					    // an error occurred
 | 
				
			||||||
    state_ = State::FAILED;
 | 
					    state_ = State::FAILED;
 | 
				
			||||||
    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
					    HELPER_LOG("Socket write failed with errno %d", errno);
 | 
				
			||||||
    return APIError::SOCKET_WRITE_FAILED;
 | 
					    return APIError::SOCKET_WRITE_FAILED;
 | 
				
			||||||
  } else if (sent != total_write_len) {
 | 
					  } else if ((size_t) sent != total_write_len) {
 | 
				
			||||||
    // partially sent, add end to tx_buf
 | 
					    // partially sent, add end to tx_buf
 | 
				
			||||||
    size_t to_consume = sent;
 | 
					    size_t to_consume = sent;
 | 
				
			||||||
    for (int i = 0; i < iovcnt; i++) {
 | 
					    for (int i = 0; i < iovcnt; i++) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,9 +116,9 @@ class APINoiseFrameHelper : public APIFrameHelper {
 | 
				
			|||||||
  std::vector<uint8_t> prologue_;
 | 
					  std::vector<uint8_t> prologue_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  std::shared_ptr<APINoiseContext> ctx_;
 | 
					  std::shared_ptr<APINoiseContext> ctx_;
 | 
				
			||||||
  NoiseHandshakeState *handshake_ = nullptr;
 | 
					  NoiseHandshakeState *handshake_{nullptr};
 | 
				
			||||||
  NoiseCipherState *send_cipher_ = nullptr;
 | 
					  NoiseCipherState *send_cipher_{nullptr};
 | 
				
			||||||
  NoiseCipherState *recv_cipher_ = nullptr;
 | 
					  NoiseCipherState *recv_cipher_{nullptr};
 | 
				
			||||||
  NoiseProtocolId nid_;
 | 
					  NoiseProtocolId nid_;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  enum class State {
 | 
					  enum class State {
 | 
				
			||||||
 
 | 
				
			|||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -53,6 +53,7 @@ enum SensorStateClass : uint32_t {
 | 
				
			|||||||
  STATE_CLASS_NONE = 0,
 | 
					  STATE_CLASS_NONE = 0,
 | 
				
			||||||
  STATE_CLASS_MEASUREMENT = 1,
 | 
					  STATE_CLASS_MEASUREMENT = 1,
 | 
				
			||||||
  STATE_CLASS_TOTAL_INCREASING = 2,
 | 
					  STATE_CLASS_TOTAL_INCREASING = 2,
 | 
				
			||||||
 | 
					  STATE_CLASS_TOTAL = 3,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
enum SensorLastResetType : uint32_t {
 | 
					enum SensorLastResetType : uint32_t {
 | 
				
			||||||
  LAST_RESET_NONE = 0,
 | 
					  LAST_RESET_NONE = 0,
 | 
				
			||||||
@@ -123,12 +124,53 @@ enum ClimatePreset : uint32_t {
 | 
				
			|||||||
  CLIMATE_PRESET_SLEEP = 6,
 | 
					  CLIMATE_PRESET_SLEEP = 6,
 | 
				
			||||||
  CLIMATE_PRESET_ACTIVITY = 7,
 | 
					  CLIMATE_PRESET_ACTIVITY = 7,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					enum NumberMode : uint32_t {
 | 
				
			||||||
 | 
					  NUMBER_MODE_AUTO = 0,
 | 
				
			||||||
 | 
					  NUMBER_MODE_BOX = 1,
 | 
				
			||||||
 | 
					  NUMBER_MODE_SLIDER = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					enum LockState : uint32_t {
 | 
				
			||||||
 | 
					  LOCK_STATE_NONE = 0,
 | 
				
			||||||
 | 
					  LOCK_STATE_LOCKED = 1,
 | 
				
			||||||
 | 
					  LOCK_STATE_UNLOCKED = 2,
 | 
				
			||||||
 | 
					  LOCK_STATE_JAMMED = 3,
 | 
				
			||||||
 | 
					  LOCK_STATE_LOCKING = 4,
 | 
				
			||||||
 | 
					  LOCK_STATE_UNLOCKING = 5,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					enum LockCommand : uint32_t {
 | 
				
			||||||
 | 
					  LOCK_UNLOCK = 0,
 | 
				
			||||||
 | 
					  LOCK_LOCK = 1,
 | 
				
			||||||
 | 
					  LOCK_OPEN = 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					enum MediaPlayerState : uint32_t {
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_NONE = 0,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_IDLE = 1,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_PLAYING = 2,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_STATE_PAUSED = 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					enum MediaPlayerCommand : uint32_t {
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_PLAY = 0,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_PAUSE = 1,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_STOP = 2,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_MUTE = 3,
 | 
				
			||||||
 | 
					  MEDIA_PLAYER_COMMAND_UNMUTE = 4,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					enum BluetoothDeviceRequestType : uint32_t {
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT = 0,
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_DISCONNECT = 1,
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_PAIR = 2,
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_UNPAIR = 3,
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITH_CACHE = 4,
 | 
				
			||||||
 | 
					  BLUETOOTH_DEVICE_REQUEST_TYPE_CONNECT_V3_WITHOUT_CACHE = 5,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace enums
 | 
					}  // namespace enums
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HelloRequest : public ProtoMessage {
 | 
					class HelloRequest : public ProtoMessage {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  std::string client_info{};
 | 
					  std::string client_info{};
 | 
				
			||||||
 | 
					  uint32_t api_version_major{0};
 | 
				
			||||||
 | 
					  uint32_t api_version_minor{0};
 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -136,12 +178,14 @@ class HelloRequest : public ProtoMessage {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
class HelloResponse : public ProtoMessage {
 | 
					class HelloResponse : public ProtoMessage {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  uint32_t api_version_major{0};
 | 
					  uint32_t api_version_major{0};
 | 
				
			||||||
  uint32_t api_version_minor{0};
 | 
					  uint32_t api_version_minor{0};
 | 
				
			||||||
  std::string server_info{};
 | 
					  std::string server_info{};
 | 
				
			||||||
 | 
					  std::string name{};
 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -230,6 +274,8 @@ class DeviceInfoResponse : public ProtoMessage {
 | 
				
			|||||||
  std::string project_name{};
 | 
					  std::string project_name{};
 | 
				
			||||||
  std::string project_version{};
 | 
					  std::string project_version{};
 | 
				
			||||||
  uint32_t webserver_port{0};
 | 
					  uint32_t webserver_port{0};
 | 
				
			||||||
 | 
					  uint32_t bluetooth_proxy_version{0};
 | 
				
			||||||
 | 
					  std::string manufacturer{};
 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -561,6 +607,7 @@ class ListEntitiesSwitchResponse : public ProtoMessage {
 | 
				
			|||||||
  bool assumed_state{false};
 | 
					  bool assumed_state{false};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					  enums::EntityCategory entity_category{};
 | 
				
			||||||
 | 
					  std::string device_class{};
 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -957,6 +1004,9 @@ class ListEntitiesNumberResponse : public ProtoMessage {
 | 
				
			|||||||
  float step{0.0f};
 | 
					  float step{0.0f};
 | 
				
			||||||
  bool disabled_by_default{false};
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
  enums::EntityCategory entity_category{};
 | 
					  enums::EntityCategory entity_category{};
 | 
				
			||||||
 | 
					  std::string unit_of_measurement{};
 | 
				
			||||||
 | 
					  enums::NumberMode mode{};
 | 
				
			||||||
 | 
					  std::string device_class{};
 | 
				
			||||||
  void encode(ProtoWriteBuffer buffer) const override;
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
  void dump_to(std::string &out) const override;
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
@@ -1041,6 +1091,440 @@ class SelectCommandRequest : public ProtoMessage {
 | 
				
			|||||||
  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					class ListEntitiesLockResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::string object_id{};
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  std::string name{};
 | 
				
			||||||
 | 
					  std::string unique_id{};
 | 
				
			||||||
 | 
					  std::string icon{};
 | 
				
			||||||
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
 | 
					  enums::EntityCategory entity_category{};
 | 
				
			||||||
 | 
					  bool assumed_state{false};
 | 
				
			||||||
 | 
					  bool supports_open{false};
 | 
				
			||||||
 | 
					  bool requires_code{false};
 | 
				
			||||||
 | 
					  std::string code_format{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class LockStateResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  enums::LockState state{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class LockCommandRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  enums::LockCommand command{};
 | 
				
			||||||
 | 
					  bool has_code{false};
 | 
				
			||||||
 | 
					  std::string code{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class ListEntitiesButtonResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::string object_id{};
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  std::string name{};
 | 
				
			||||||
 | 
					  std::string unique_id{};
 | 
				
			||||||
 | 
					  std::string icon{};
 | 
				
			||||||
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
 | 
					  enums::EntityCategory entity_category{};
 | 
				
			||||||
 | 
					  std::string device_class{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class ButtonCommandRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class ListEntitiesMediaPlayerResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::string object_id{};
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  std::string name{};
 | 
				
			||||||
 | 
					  std::string unique_id{};
 | 
				
			||||||
 | 
					  std::string icon{};
 | 
				
			||||||
 | 
					  bool disabled_by_default{false};
 | 
				
			||||||
 | 
					  enums::EntityCategory entity_category{};
 | 
				
			||||||
 | 
					  bool supports_pause{false};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class MediaPlayerStateResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  enums::MediaPlayerState state{};
 | 
				
			||||||
 | 
					  float volume{0.0f};
 | 
				
			||||||
 | 
					  bool muted{false};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class MediaPlayerCommandRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t key{0};
 | 
				
			||||||
 | 
					  bool has_command{false};
 | 
				
			||||||
 | 
					  enums::MediaPlayerCommand command{};
 | 
				
			||||||
 | 
					  bool has_volume{false};
 | 
				
			||||||
 | 
					  float volume{0.0f};
 | 
				
			||||||
 | 
					  bool has_media_url{false};
 | 
				
			||||||
 | 
					  std::string media_url{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_32bit(uint32_t field_id, Proto32Bit value) override;
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class SubscribeBluetoothLEAdvertisementsRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothServiceData : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::string uuid{};
 | 
				
			||||||
 | 
					  std::vector<uint32_t> legacy_data{};
 | 
				
			||||||
 | 
					  std::string data{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothLEAdvertisementResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  std::string name{};
 | 
				
			||||||
 | 
					  int32_t rssi{0};
 | 
				
			||||||
 | 
					  std::vector<std::string> service_uuids{};
 | 
				
			||||||
 | 
					  std::vector<BluetoothServiceData> service_data{};
 | 
				
			||||||
 | 
					  std::vector<BluetoothServiceData> manufacturer_data{};
 | 
				
			||||||
 | 
					  uint32_t address_type{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothDeviceRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  enums::BluetoothDeviceRequestType request_type{};
 | 
				
			||||||
 | 
					  bool has_address_type{false};
 | 
				
			||||||
 | 
					  uint32_t address_type{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothDeviceConnectionResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  bool connected{false};
 | 
				
			||||||
 | 
					  uint32_t mtu{0};
 | 
				
			||||||
 | 
					  int32_t error{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTGetServicesRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTDescriptor : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::vector<uint64_t> uuid{};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTCharacteristic : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::vector<uint64_t> uuid{};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  uint32_t properties{0};
 | 
				
			||||||
 | 
					  std::vector<BluetoothGATTDescriptor> descriptors{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTService : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  std::vector<uint64_t> uuid{};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  std::vector<BluetoothGATTCharacteristic> characteristics{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTGetServicesResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  std::vector<BluetoothGATTService> services{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTGetServicesDoneResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTReadRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTReadResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  std::string data{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTWriteRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  bool response{false};
 | 
				
			||||||
 | 
					  std::string data{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTReadDescriptorRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTWriteDescriptorRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  std::string data{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTNotifyRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  bool enable{false};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTNotifyDataResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  std::string data{};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class SubscribeBluetoothConnectionsFreeRequest : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothConnectionsFreeResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint32_t free{0};
 | 
				
			||||||
 | 
					  uint32_t limit{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTErrorResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  int32_t error{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTWriteResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					class BluetoothGATTNotifyResponse : public ProtoMessage {
 | 
				
			||||||
 | 
					 public:
 | 
				
			||||||
 | 
					  uint64_t address{0};
 | 
				
			||||||
 | 
					  uint32_t handle{0};
 | 
				
			||||||
 | 
					  void encode(ProtoWriteBuffer buffer) const override;
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  void dump_to(std::string &out) const override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 protected:
 | 
				
			||||||
 | 
					  bool decode_varint(uint32_t field_id, ProtoVarInt value) override;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -282,6 +282,149 @@ bool APIServerConnectionBase::send_select_state_response(const SelectStateRespon
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_list_entities_lock_response(const ListEntitiesLockResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_list_entities_lock_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<ListEntitiesLockResponse>(msg, 58);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_lock_state_response(const LockStateResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_lock_state_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<LockStateResponse>(msg, 59);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_list_entities_button_response(const ListEntitiesButtonResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_list_entities_button_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<ListEntitiesButtonResponse>(msg, 61);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_list_entities_media_player_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<ListEntitiesMediaPlayerResponse>(msg, 63);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_media_player_state_response(const MediaPlayerStateResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_media_player_state_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<MediaPlayerStateResponse>(msg, 64);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_le_advertisement_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothLEAdvertisementResponse>(msg, 67);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_device_connection_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothDeviceConnectionResponse>(msg, 69);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTGetServicesResponse>(msg, 71);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_get_services_done_response(
 | 
				
			||||||
 | 
					    const BluetoothGATTGetServicesDoneResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_get_services_done_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTGetServicesDoneResponse>(msg, 72);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_read_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTReadResponse>(msg, 74);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_notify_data_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTNotifyDataResponse>(msg, 79);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_connections_free_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothConnectionsFreeResponse>(msg, 81);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_error_response(const BluetoothGATTErrorResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_error_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTErrorResponse>(msg, 82);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_write_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTWriteResponse>(msg, 83);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					bool APIServerConnectionBase::send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg) {
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					  ESP_LOGVV(TAG, "send_bluetooth_gatt_notify_response: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  return this->send_message_<BluetoothGATTNotifyResponse>(msg, 84);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
 | 
					bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) {
 | 
				
			||||||
  switch (msg_type) {
 | 
					  switch (msg_type) {
 | 
				
			||||||
    case 1: {
 | 
					    case 1: {
 | 
				
			||||||
@@ -513,6 +656,136 @@ bool APIServerConnectionBase::read_message(uint32_t msg_size, uint32_t msg_type,
 | 
				
			|||||||
      ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
 | 
					      ESP_LOGVV(TAG, "on_select_command_request: %s", msg.dump().c_str());
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
      this->on_select_command_request(msg);
 | 
					      this->on_select_command_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 60: {
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					      LockCommandRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_lock_command_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_lock_command_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 62: {
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					      ButtonCommandRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_button_command_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_button_command_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 65: {
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					      MediaPlayerCommandRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_media_player_command_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_media_player_command_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 66: {
 | 
				
			||||||
 | 
					      SubscribeBluetoothLEAdvertisementsRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_subscribe_bluetooth_le_advertisements_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_subscribe_bluetooth_le_advertisements_request(msg);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 68: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothDeviceRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_device_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_device_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 70: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTGetServicesRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_get_services_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_get_services_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 73: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTReadRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_read_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_read_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 75: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTWriteRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_write_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_write_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 76: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTReadDescriptorRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_read_descriptor_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_read_descriptor_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 77: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTWriteDescriptorRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_write_descriptor_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_write_descriptor_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 78: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      BluetoothGATTNotifyRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_bluetooth_gatt_notify_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_bluetooth_gatt_notify_request(msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    case 80: {
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					      SubscribeBluetoothConnectionsFreeRequest msg;
 | 
				
			||||||
 | 
					      msg.decode(msg_data, msg_size);
 | 
				
			||||||
 | 
					#ifdef HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
 | 
					      ESP_LOGVV(TAG, "on_subscribe_bluetooth_connections_free_request: %s", msg.dump().c_str());
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					      this->on_subscribe_bluetooth_connections_free_request(msg);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -737,6 +1010,165 @@ void APIServerConnection::on_select_command_request(const SelectCommandRequest &
 | 
				
			|||||||
  this->select_command(msg);
 | 
					  this->select_command(msg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					void APIServerConnection::on_button_command_request(const ButtonCommandRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->button_command(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					void APIServerConnection::on_lock_command_request(const LockCommandRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->lock_command(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					void APIServerConnection::on_media_player_command_request(const MediaPlayerCommandRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->media_player_command(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					void APIServerConnection::on_subscribe_bluetooth_le_advertisements_request(
 | 
				
			||||||
 | 
					    const SubscribeBluetoothLEAdvertisementsRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->subscribe_bluetooth_le_advertisements(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_device_request(const BluetoothDeviceRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_device_request(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_get_services(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_read(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_write(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_read_descriptor(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_write_descriptor(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  this->bluetooth_gatt_notify(msg);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServerConnection::on_subscribe_bluetooth_connections_free_request(
 | 
				
			||||||
 | 
					    const SubscribeBluetoothConnectionsFreeRequest &msg) {
 | 
				
			||||||
 | 
					  if (!this->is_connection_setup()) {
 | 
				
			||||||
 | 
					    this->on_no_setup_connection();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  if (!this->is_authenticated()) {
 | 
				
			||||||
 | 
					    this->on_unauthenticated_access();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  BluetoothConnectionsFreeResponse ret = this->subscribe_bluetooth_connections_free(msg);
 | 
				
			||||||
 | 
					  if (!this->send_bluetooth_connections_free_response(ret)) {
 | 
				
			||||||
 | 
					    this->on_fatal_error();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,6 +129,86 @@ class APIServerConnectionBase : public ProtoService {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  virtual void on_select_command_request(const SelectCommandRequest &value){};
 | 
					  virtual void on_select_command_request(const SelectCommandRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  bool send_list_entities_lock_response(const ListEntitiesLockResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  bool send_lock_state_response(const LockStateResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  virtual void on_lock_command_request(const LockCommandRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  bool send_list_entities_button_response(const ListEntitiesButtonResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  virtual void on_button_command_request(const ButtonCommandRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  bool send_list_entities_media_player_response(const ListEntitiesMediaPlayerResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  bool send_media_player_state_response(const MediaPlayerStateResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  virtual void on_media_player_command_request(const MediaPlayerCommandRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  virtual void on_subscribe_bluetooth_le_advertisements_request(
 | 
				
			||||||
 | 
					      const SubscribeBluetoothLEAdvertisementsRequest &value){};
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_le_advertisement_response(const BluetoothLEAdvertisementResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_device_request(const BluetoothDeviceRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_device_connection_response(const BluetoothDeviceConnectionResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_get_services_response(const BluetoothGATTGetServicesResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_get_services_done_response(const BluetoothGATTGetServicesDoneResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &value){};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_connections_free_response(const BluetoothConnectionsFreeResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_error_response(const BluetoothGATTErrorResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &msg);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  bool send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &msg);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
 | 
					  bool read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) override;
 | 
				
			||||||
@@ -171,6 +251,41 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  virtual void select_command(const SelectCommandRequest &msg) = 0;
 | 
					  virtual void select_command(const SelectCommandRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  virtual void button_command(const ButtonCommandRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  virtual void lock_command(const LockCommandRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  virtual void media_player_command(const MediaPlayerCommandRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  virtual void subscribe_bluetooth_le_advertisements(const SubscribeBluetoothLEAdvertisementsRequest &msg) = 0;
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_device_request(const BluetoothDeviceRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_get_services(const BluetoothGATTGetServicesRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_read(const BluetoothGATTReadRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_write(const BluetoothGATTWriteRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_read_descriptor(const BluetoothGATTReadDescriptorRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_write_descriptor(const BluetoothGATTWriteDescriptorRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual void bluetooth_gatt_notify(const BluetoothGATTNotifyRequest &msg) = 0;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  virtual BluetoothConnectionsFreeResponse subscribe_bluetooth_connections_free(
 | 
				
			||||||
 | 
					      const SubscribeBluetoothConnectionsFreeRequest &msg) = 0;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 protected:
 | 
					 protected:
 | 
				
			||||||
  void on_hello_request(const HelloRequest &msg) override;
 | 
					  void on_hello_request(const HelloRequest &msg) override;
 | 
				
			||||||
@@ -209,6 +324,40 @@ class APIServerConnection : public APIServerConnectionBase {
 | 
				
			|||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  void on_select_command_request(const SelectCommandRequest &msg) override;
 | 
					  void on_select_command_request(const SelectCommandRequest &msg) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  void on_button_command_request(const ButtonCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  void on_lock_command_request(const LockCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  void on_media_player_command_request(const MediaPlayerCommandRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  void on_subscribe_bluetooth_le_advertisements_request(const SubscribeBluetoothLEAdvertisementsRequest &msg) override;
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_device_request(const BluetoothDeviceRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_get_services_request(const BluetoothGATTGetServicesRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_read_request(const BluetoothGATTReadRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_write_request(const BluetoothGATTWriteRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_read_descriptor_request(const BluetoothGATTReadDescriptorRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_write_descriptor_request(const BluetoothGATTWriteDescriptorRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_bluetooth_gatt_notify_request(const BluetoothGATTNotifyRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void on_subscribe_bluetooth_connections_free_request(const SubscribeBluetoothConnectionsFreeRequest &msg) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,7 +24,7 @@ static const char *const TAG = "api";
 | 
				
			|||||||
void APIServer::setup() {
 | 
					void APIServer::setup() {
 | 
				
			||||||
  ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
 | 
					  ESP_LOGCONFIG(TAG, "Setting up Home Assistant API server...");
 | 
				
			||||||
  this->setup_controller();
 | 
					  this->setup_controller();
 | 
				
			||||||
  socket_ = socket::socket(AF_INET, SOCK_STREAM, 0);
 | 
					  socket_ = socket::socket_ip(SOCK_STREAM, 0);
 | 
				
			||||||
  if (socket_ == nullptr) {
 | 
					  if (socket_ == nullptr) {
 | 
				
			||||||
    ESP_LOGW(TAG, "Could not create socket.");
 | 
					    ESP_LOGW(TAG, "Could not create socket.");
 | 
				
			||||||
    this->mark_failed();
 | 
					    this->mark_failed();
 | 
				
			||||||
@@ -43,13 +43,16 @@ void APIServer::setup() {
 | 
				
			|||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  struct sockaddr_in server;
 | 
					  struct sockaddr_storage server;
 | 
				
			||||||
  memset(&server, 0, sizeof(server));
 | 
					 | 
				
			||||||
  server.sin_family = AF_INET;
 | 
					 | 
				
			||||||
  server.sin_addr.s_addr = ESPHOME_INADDR_ANY;
 | 
					 | 
				
			||||||
  server.sin_port = htons(this->port_);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  err = socket_->bind((struct sockaddr *) &server, sizeof(server));
 | 
					  socklen_t sl = socket::set_sockaddr_any((struct sockaddr *) &server, sizeof(server), htons(this->port_));
 | 
				
			||||||
 | 
					  if (sl == 0) {
 | 
				
			||||||
 | 
					    ESP_LOGW(TAG, "Socket unable to set sockaddr: errno %d", errno);
 | 
				
			||||||
 | 
					    this->mark_failed();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  err = socket_->bind((struct sockaddr *) &server, sl);
 | 
				
			||||||
  if (err != 0) {
 | 
					  if (err != 0) {
 | 
				
			||||||
    ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
 | 
					    ESP_LOGW(TAG, "Socket unable to bind: errno %d", errno);
 | 
				
			||||||
    this->mark_failed();
 | 
					    this->mark_failed();
 | 
				
			||||||
@@ -80,9 +83,10 @@ void APIServer::setup() {
 | 
				
			|||||||
  if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
 | 
					  if (esp32_camera::global_esp32_camera != nullptr && !esp32_camera::global_esp32_camera->is_internal()) {
 | 
				
			||||||
    esp32_camera::global_esp32_camera->add_image_callback(
 | 
					    esp32_camera::global_esp32_camera->add_image_callback(
 | 
				
			||||||
        [this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
 | 
					        [this](const std::shared_ptr<esp32_camera::CameraImage> &image) {
 | 
				
			||||||
          for (auto &c : this->clients_)
 | 
					          for (auto &c : this->clients_) {
 | 
				
			||||||
            if (!c->remove_)
 | 
					            if (!c->remove_)
 | 
				
			||||||
              c->send_camera_state(image);
 | 
					              c->send_camera_state(image);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -188,7 +192,7 @@ void APIServer::on_cover_update(cover::Cover *obj) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
void APIServer::on_fan_update(fan::FanState *obj) {
 | 
					void APIServer::on_fan_update(fan::Fan *obj) {
 | 
				
			||||||
  if (obj->is_internal())
 | 
					  if (obj->is_internal())
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  for (auto &c : this->clients_)
 | 
					  for (auto &c : this->clients_)
 | 
				
			||||||
@@ -251,7 +255,7 @@ void APIServer::on_number_update(number::Number *obj, float state) {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
void APIServer::on_select_update(select::Select *obj, const std::string &state) {
 | 
					void APIServer::on_select_update(select::Select *obj, const std::string &state, size_t index) {
 | 
				
			||||||
  if (obj->is_internal())
 | 
					  if (obj->is_internal())
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  for (auto &c : this->clients_)
 | 
					  for (auto &c : this->clients_)
 | 
				
			||||||
@@ -259,6 +263,24 @@ void APIServer::on_select_update(select::Select *obj, const std::string &state)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					void APIServer::on_lock_update(lock::Lock *obj) {
 | 
				
			||||||
 | 
					  if (obj->is_internal())
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  for (auto &c : this->clients_)
 | 
				
			||||||
 | 
					    c->send_lock_state(obj, obj->state);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					void APIServer::on_media_player_update(media_player::MediaPlayer *obj) {
 | 
				
			||||||
 | 
					  if (obj->is_internal())
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  for (auto &c : this->clients_)
 | 
				
			||||||
 | 
					    c->send_media_player_state(obj);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
 | 
					float APIServer::get_setup_priority() const { return setup_priority::AFTER_WIFI; }
 | 
				
			||||||
void APIServer::set_port(uint16_t port) { this->port_ = port; }
 | 
					void APIServer::set_port(uint16_t port) { this->port_ = port; }
 | 
				
			||||||
APIServer *global_api_server = nullptr;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | 
					APIServer *global_api_server = nullptr;  // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
 | 
				
			||||||
@@ -269,6 +291,79 @@ void APIServer::send_homeassistant_service_call(const HomeassistantServiceRespon
 | 
				
			|||||||
    client->send_homeassistant_service_call(call);
 | 
					    client->send_homeassistant_service_call(call);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_le_advertisement(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu, esp_err_t error) {
 | 
				
			||||||
 | 
					  BluetoothDeviceConnectionResponse call;
 | 
				
			||||||
 | 
					  call.address = address;
 | 
				
			||||||
 | 
					  call.connected = connected;
 | 
				
			||||||
 | 
					  call.mtu = mtu;
 | 
				
			||||||
 | 
					  call.error = error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_device_connection_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_connections_free(uint8_t free, uint8_t limit) {
 | 
				
			||||||
 | 
					  BluetoothConnectionsFreeResponse call;
 | 
				
			||||||
 | 
					  call.free = free;
 | 
				
			||||||
 | 
					  call.limit = limit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_connections_free_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_read_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_write_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_notify_data_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_notify_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_services(const BluetoothGATTGetServicesResponse &call) {
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_get_services_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_services_done(uint64_t address) {
 | 
				
			||||||
 | 
					  BluetoothGATTGetServicesDoneResponse call;
 | 
				
			||||||
 | 
					  call.address = address;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_get_services_done_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void APIServer::send_bluetooth_gatt_error(uint64_t address, uint16_t handle, esp_err_t error) {
 | 
				
			||||||
 | 
					  BluetoothGATTErrorResponse call;
 | 
				
			||||||
 | 
					  call.address = address;
 | 
				
			||||||
 | 
					  call.handle = handle;
 | 
				
			||||||
 | 
					  call.error = error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (auto &client : this->clients_) {
 | 
				
			||||||
 | 
					    client->send_bluetooth_gatt_error_response(call);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
APIServer::APIServer() { global_api_server = this; }
 | 
					APIServer::APIServer() { global_api_server = this; }
 | 
				
			||||||
void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
 | 
					void APIServer::subscribe_home_assistant_state(std::string entity_id, optional<std::string> attribute,
 | 
				
			||||||
                                               std::function<void(std::string)> f) {
 | 
					                                               std::function<void(std::string)> f) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,12 +7,13 @@
 | 
				
			|||||||
#include "esphome/components/socket/socket.h"
 | 
					#include "esphome/components/socket/socket.h"
 | 
				
			||||||
#include "api_pb2.h"
 | 
					#include "api_pb2.h"
 | 
				
			||||||
#include "api_pb2_service.h"
 | 
					#include "api_pb2_service.h"
 | 
				
			||||||
#include "util.h"
 | 
					 | 
				
			||||||
#include "list_entities.h"
 | 
					#include "list_entities.h"
 | 
				
			||||||
#include "subscribe_state.h"
 | 
					#include "subscribe_state.h"
 | 
				
			||||||
#include "user_services.h"
 | 
					#include "user_services.h"
 | 
				
			||||||
#include "api_noise_context.h"
 | 
					#include "api_noise_context.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -44,7 +45,7 @@ class APIServer : public Component, public Controller {
 | 
				
			|||||||
  void on_cover_update(cover::Cover *obj) override;
 | 
					  void on_cover_update(cover::Cover *obj) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
  void on_fan_update(fan::FanState *obj) override;
 | 
					  void on_fan_update(fan::Fan *obj) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
  void on_light_update(light::LightState *obj) override;
 | 
					  void on_light_update(light::LightState *obj) override;
 | 
				
			||||||
@@ -65,9 +66,27 @@ class APIServer : public Component, public Controller {
 | 
				
			|||||||
  void on_number_update(number::Number *obj, float state) override;
 | 
					  void on_number_update(number::Number *obj, float state) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  void on_select_update(select::Select *obj, const std::string &state) override;
 | 
					  void on_select_update(select::Select *obj, const std::string &state, size_t index) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  void on_lock_update(lock::Lock *obj) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  void on_media_player_update(media_player::MediaPlayer *obj) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  void send_homeassistant_service_call(const HomeassistantServiceResponse &call);
 | 
					  void send_homeassistant_service_call(const HomeassistantServiceResponse &call);
 | 
				
			||||||
 | 
					#ifdef USE_BLUETOOTH_PROXY
 | 
				
			||||||
 | 
					  void send_bluetooth_le_advertisement(const BluetoothLEAdvertisementResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_device_connection(uint64_t address, bool connected, uint16_t mtu = 0, esp_err_t error = ESP_OK);
 | 
				
			||||||
 | 
					  void send_bluetooth_connections_free(uint8_t free, uint8_t limit);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_read_response(const BluetoothGATTReadResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_write_response(const BluetoothGATTWriteResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_notify_data_response(const BluetoothGATTNotifyDataResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_notify_response(const BluetoothGATTNotifyResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_services(const BluetoothGATTGetServicesResponse &call);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_services_done(uint64_t address);
 | 
				
			||||||
 | 
					  void send_bluetooth_gatt_error(uint64_t address, uint16_t handle, esp_err_t error);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
 | 
					  void register_user_service(UserServiceDescriptor *descriptor) { this->user_services_.push_back(descriptor); }
 | 
				
			||||||
#ifdef USE_HOMEASSISTANT_TIME
 | 
					#ifdef USE_HOMEASSISTANT_TIME
 | 
				
			||||||
  void request_time();
 | 
					  void request_time();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,7 +21,6 @@ async def async_run_logs(config, address):
 | 
				
			|||||||
    if CONF_ENCRYPTION in conf:
 | 
					    if CONF_ENCRYPTION in conf:
 | 
				
			||||||
        noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
 | 
					        noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
 | 
				
			||||||
    _LOGGER.info("Starting log output from %s using esphome API", address)
 | 
					    _LOGGER.info("Starting log output from %s using esphome API", address)
 | 
				
			||||||
    zc = zeroconf.Zeroconf()
 | 
					 | 
				
			||||||
    cli = APIClient(
 | 
					    cli = APIClient(
 | 
				
			||||||
        address,
 | 
					        address,
 | 
				
			||||||
        port,
 | 
					        port,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
#include "api_pb2.h"
 | 
					#include "api_pb2.h"
 | 
				
			||||||
#include "api_server.h"
 | 
					#include "api_server.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -12,10 +14,10 @@ template<typename... X> class TemplatableStringValue : public TemplatableValue<s
 | 
				
			|||||||
 public:
 | 
					 public:
 | 
				
			||||||
  TemplatableStringValue() : TemplatableValue<std::string, X...>() {}
 | 
					  TemplatableStringValue() : TemplatableValue<std::string, X...>() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template<typename F, enable_if_t<!is_callable<F, X...>::value, int> = 0>
 | 
					  template<typename F, enable_if_t<!is_invocable<F, X...>::value, int> = 0>
 | 
				
			||||||
  TemplatableStringValue(F value) : TemplatableValue<std::string, X...>(value) {}
 | 
					  TemplatableStringValue(F value) : TemplatableValue<std::string, X...>(value) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  template<typename F, enable_if_t<is_callable<F, X...>::value, int> = 0>
 | 
					  template<typename F, enable_if_t<is_invocable<F, X...>::value, int> = 0>
 | 
				
			||||||
  TemplatableStringValue(F f)
 | 
					  TemplatableStringValue(F f)
 | 
				
			||||||
      : TemplatableValue<std::string, X...>([f](X... x) -> std::string { return to_string(f(x...)); }) {}
 | 
					      : TemplatableValue<std::string, X...>([f](X... x) -> std::string { return to_string(f(x...)); }) {}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,7 +16,7 @@ bool ListEntitiesIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_
 | 
				
			|||||||
bool ListEntitiesIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_info(cover); }
 | 
					bool ListEntitiesIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_info(cover); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
bool ListEntitiesIterator::on_fan(fan::FanState *fan) { return this->client_->send_fan_info(fan); }
 | 
					bool ListEntitiesIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_info(fan); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
bool ListEntitiesIterator::on_light(light::LightState *light) { return this->client_->send_light_info(light); }
 | 
					bool ListEntitiesIterator::on_light(light::LightState *light) { return this->client_->send_light_info(light); }
 | 
				
			||||||
@@ -27,15 +27,20 @@ bool ListEntitiesIterator::on_sensor(sensor::Sensor *sensor) { return this->clie
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_info(a_switch); }
 | 
					bool ListEntitiesIterator::on_switch(switch_::Switch *a_switch) { return this->client_->send_switch_info(a_switch); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					bool ListEntitiesIterator::on_button(button::Button *button) { return this->client_->send_button_info(button); }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
 | 
					bool ListEntitiesIterator::on_text_sensor(text_sensor::TextSensor *text_sensor) {
 | 
				
			||||||
  return this->client_->send_text_sensor_info(text_sensor);
 | 
					  return this->client_->send_text_sensor_info(text_sensor);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					bool ListEntitiesIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_info(a_lock); }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
 | 
					bool ListEntitiesIterator::on_end() { return this->client_->send_list_info_done(); }
 | 
				
			||||||
ListEntitiesIterator::ListEntitiesIterator(APIServer *server, APIConnection *client)
 | 
					ListEntitiesIterator::ListEntitiesIterator(APIConnection *client) : client_(client) {}
 | 
				
			||||||
    : ComponentIterator(server), client_(client) {}
 | 
					 | 
				
			||||||
bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
 | 
					bool ListEntitiesIterator::on_service(UserServiceDescriptor *service) {
 | 
				
			||||||
  auto resp = service->encode_list_service_response();
 | 
					  auto resp = service->encode_list_service_response();
 | 
				
			||||||
  return this->client_->send_list_entities_services_response(resp);
 | 
					  return this->client_->send_list_entities_services_response(resp);
 | 
				
			||||||
@@ -59,5 +64,11 @@ bool ListEntitiesIterator::on_number(number::Number *number) { return this->clie
 | 
				
			|||||||
bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
 | 
					bool ListEntitiesIterator::on_select(select::Select *select) { return this->client_->send_select_info(select); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					bool ListEntitiesIterator::on_media_player(media_player::MediaPlayer *media_player) {
 | 
				
			||||||
 | 
					  return this->client_->send_media_player_info(media_player);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "esphome/core/component.h"
 | 
					#include "esphome/core/component.h"
 | 
				
			||||||
 | 
					#include "esphome/core/component_iterator.h"
 | 
				
			||||||
#include "esphome/core/defines.h"
 | 
					#include "esphome/core/defines.h"
 | 
				
			||||||
#include "util.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
namespace api {
 | 
					namespace api {
 | 
				
			||||||
@@ -11,7 +11,7 @@ class APIConnection;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class ListEntitiesIterator : public ComponentIterator {
 | 
					class ListEntitiesIterator : public ComponentIterator {
 | 
				
			||||||
 public:
 | 
					 public:
 | 
				
			||||||
  ListEntitiesIterator(APIServer *server, APIConnection *client);
 | 
					  ListEntitiesIterator(APIConnection *client);
 | 
				
			||||||
#ifdef USE_BINARY_SENSOR
 | 
					#ifdef USE_BINARY_SENSOR
 | 
				
			||||||
  bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
 | 
					  bool on_binary_sensor(binary_sensor::BinarySensor *binary_sensor) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -19,7 +19,7 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
				
			|||||||
  bool on_cover(cover::Cover *cover) override;
 | 
					  bool on_cover(cover::Cover *cover) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
  bool on_fan(fan::FanState *fan) override;
 | 
					  bool on_fan(fan::Fan *fan) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
  bool on_light(light::LightState *light) override;
 | 
					  bool on_light(light::LightState *light) override;
 | 
				
			||||||
@@ -30,6 +30,9 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
				
			|||||||
#ifdef USE_SWITCH
 | 
					#ifdef USE_SWITCH
 | 
				
			||||||
  bool on_switch(switch_::Switch *a_switch) override;
 | 
					  bool on_switch(switch_::Switch *a_switch) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_BUTTON
 | 
				
			||||||
 | 
					  bool on_button(button::Button *button) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
#ifdef USE_TEXT_SENSOR
 | 
					#ifdef USE_TEXT_SENSOR
 | 
				
			||||||
  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
					  bool on_text_sensor(text_sensor::TextSensor *text_sensor) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -45,6 +48,12 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_SELECT
 | 
					#ifdef USE_SELECT
 | 
				
			||||||
  bool on_select(select::Select *select) override;
 | 
					  bool on_select(select::Select *select) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
 | 
					  bool on_lock(lock::Lock *a_lock) override;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					  bool on_media_player(media_player::MediaPlayer *media_player) override;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  bool on_end() override;
 | 
					  bool on_end() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -54,5 +63,3 @@ class ListEntitiesIterator : public ComponentIterator {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "api_server.h"
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,4 @@
 | 
				
			|||||||
#include "proto.h"
 | 
					#include "proto.h"
 | 
				
			||||||
#include "util.h"
 | 
					 | 
				
			||||||
#include "esphome/core/log.h"
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace esphome {
 | 
					namespace esphome {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@
 | 
				
			|||||||
#include "esphome/core/log.h"
 | 
					#include "esphome/core/log.h"
 | 
				
			||||||
#include "esphome/core/helpers.h"
 | 
					#include "esphome/core/helpers.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <vector>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
 | 
					#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
 | 
				
			||||||
#define HAS_PROTO_MESSAGE_DUMP
 | 
					#define HAS_PROTO_MESSAGE_DUMP
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@@ -55,20 +57,22 @@ class ProtoVarInt {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  int32_t as_sint32() const {
 | 
					  int32_t as_sint32() const {
 | 
				
			||||||
    // with ZigZag encoding
 | 
					    // with ZigZag encoding
 | 
				
			||||||
    if (this->value_ & 1)
 | 
					    if (this->value_ & 1) {
 | 
				
			||||||
      return static_cast<int32_t>(~(this->value_ >> 1));
 | 
					      return static_cast<int32_t>(~(this->value_ >> 1));
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
      return static_cast<int32_t>(this->value_ >> 1);
 | 
					      return static_cast<int32_t>(this->value_ >> 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  int64_t as_sint64() const {
 | 
					  int64_t as_sint64() const {
 | 
				
			||||||
    // with ZigZag encoding
 | 
					    // with ZigZag encoding
 | 
				
			||||||
    if (this->value_ & 1)
 | 
					    if (this->value_ & 1) {
 | 
				
			||||||
      return static_cast<int64_t>(~(this->value_ >> 1));
 | 
					      return static_cast<int64_t>(~(this->value_ >> 1));
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
      return static_cast<int64_t>(this->value_ >> 1);
 | 
					      return static_cast<int64_t>(this->value_ >> 1);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  void encode(std::vector<uint8_t> &out) {
 | 
					  void encode(std::vector<uint8_t> &out) {
 | 
				
			||||||
    uint32_t val = this->value_;
 | 
					    uint64_t val = this->value_;
 | 
				
			||||||
    if (val <= 0x7F) {
 | 
					    if (val <= 0x7F) {
 | 
				
			||||||
      out.push_back(val);
 | 
					      out.push_back(val);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
@@ -193,6 +197,20 @@ class ProtoWriteBuffer {
 | 
				
			|||||||
    this->write((value >> 16) & 0xFF);
 | 
					    this->write((value >> 16) & 0xFF);
 | 
				
			||||||
    this->write((value >> 24) & 0xFF);
 | 
					    this->write((value >> 24) & 0xFF);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  void encode_fixed64(uint32_t field_id, uint64_t value, bool force = false) {
 | 
				
			||||||
 | 
					    if (value == 0 && !force)
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this->encode_field_raw(field_id, 5);
 | 
				
			||||||
 | 
					    this->write((value >> 0) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 8) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 16) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 24) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 32) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 40) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 48) & 0xFF);
 | 
				
			||||||
 | 
					    this->write((value >> 56) & 0xFF);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  template<typename T> void encode_enum(uint32_t field_id, T value, bool force = false) {
 | 
					  template<typename T> void encode_enum(uint32_t field_id, T value, bool force = false) {
 | 
				
			||||||
    this->encode_uint32(field_id, static_cast<uint32_t>(value), force);
 | 
					    this->encode_uint32(field_id, static_cast<uint32_t>(value), force);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -220,12 +238,22 @@ class ProtoWriteBuffer {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
 | 
					  void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
 | 
				
			||||||
    uint32_t uvalue;
 | 
					    uint32_t uvalue;
 | 
				
			||||||
    if (value < 0)
 | 
					    if (value < 0) {
 | 
				
			||||||
      uvalue = ~(value << 1);
 | 
					      uvalue = ~(value << 1);
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
      uvalue = value << 1;
 | 
					      uvalue = value << 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    this->encode_uint32(field_id, uvalue, force);
 | 
					    this->encode_uint32(field_id, uvalue, force);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
 | 
				
			||||||
 | 
					    uint64_t uvalue;
 | 
				
			||||||
 | 
					    if (value < 0) {
 | 
				
			||||||
 | 
					      uvalue = ~(value << 1);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					      uvalue = value << 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this->encode_uint64(field_id, uvalue, force);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  template<class C> void encode_message(uint32_t field_id, const C &value, bool force = false) {
 | 
					  template<class C> void encode_message(uint32_t field_id, const C &value, bool force = false) {
 | 
				
			||||||
    this->encode_field_raw(field_id, 2);
 | 
					    this->encode_field_raw(field_id, 2);
 | 
				
			||||||
    size_t begin = this->buffer_->size();
 | 
					    size_t begin = this->buffer_->size();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,7 +14,7 @@ bool InitialStateIterator::on_binary_sensor(binary_sensor::BinarySensor *binary_
 | 
				
			|||||||
bool InitialStateIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_state(cover); }
 | 
					bool InitialStateIterator::on_cover(cover::Cover *cover) { return this->client_->send_cover_state(cover); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_FAN
 | 
					#ifdef USE_FAN
 | 
				
			||||||
bool InitialStateIterator::on_fan(fan::FanState *fan) { return this->client_->send_fan_state(fan); }
 | 
					bool InitialStateIterator::on_fan(fan::Fan *fan) { return this->client_->send_fan_state(fan); }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#ifdef USE_LIGHT
 | 
					#ifdef USE_LIGHT
 | 
				
			||||||
bool InitialStateIterator::on_light(light::LightState *light) { return this->client_->send_light_state(light); }
 | 
					bool InitialStateIterator::on_light(light::LightState *light) { return this->client_->send_light_state(light); }
 | 
				
			||||||
@@ -47,8 +47,15 @@ bool InitialStateIterator::on_select(select::Select *select) {
 | 
				
			|||||||
  return this->client_->send_select_state(select, select->state);
 | 
					  return this->client_->send_select_state(select, select->state);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
InitialStateIterator::InitialStateIterator(APIServer *server, APIConnection *client)
 | 
					#ifdef USE_LOCK
 | 
				
			||||||
    : ComponentIterator(server), client_(client) {}
 | 
					bool InitialStateIterator::on_lock(lock::Lock *a_lock) { return this->client_->send_lock_state(a_lock, a_lock->state); }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifdef USE_MEDIA_PLAYER
 | 
				
			||||||
 | 
					bool InitialStateIterator::on_media_player(media_player::MediaPlayer *media_player) {
 | 
				
			||||||
 | 
					  return this->client_->send_media_player_state(media_player);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					InitialStateIterator::InitialStateIterator(APIConnection *client) : client_(client) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}  // namespace api
 | 
					}  // namespace api
 | 
				
			||||||
}  // namespace esphome
 | 
					}  // namespace esphome
 | 
				
			||||||
 
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user