mirror of
https://github.com/home-assistant/core.git
synced 2025-09-20 10:29:26 +00:00
Compare commits
2320 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1c534ea027 | ||
![]() |
5cb5a508a8 | ||
![]() |
c693d8af14 | ||
![]() |
9d56d3bb31 | ||
![]() |
9bdc716e60 | ||
![]() |
8a16fb53c8 | ||
![]() |
2076fc59c4 | ||
![]() |
1d816d25f7 | ||
![]() |
e85d1deddd | ||
![]() |
5658abfaca | ||
![]() |
42ad36e9f8 | ||
![]() |
082f866620 | ||
![]() |
ac71641c18 | ||
![]() |
a11fd08d20 | ||
![]() |
4c157f65ea | ||
![]() |
01a0ffa636 | ||
![]() |
f454b4154b | ||
![]() |
ab3909c24f | ||
![]() |
9ccebdb8d5 | ||
![]() |
e7d8742771 | ||
![]() |
30effb5c8a | ||
![]() |
27350f41c9 | ||
![]() |
fc0344399b | ||
![]() |
d9ba32dc3f | ||
![]() |
aada6a1d88 | ||
![]() |
729ed1cab6 | ||
![]() |
205cf57a77 | ||
![]() |
d6df1527f1 | ||
![]() |
3d2d56213c | ||
![]() |
4cce724473 | ||
![]() |
dbda9a520e | ||
![]() |
c802a63700 | ||
![]() |
c6f3352cf8 | ||
![]() |
f5429dc175 | ||
![]() |
e38ae1b188 | ||
![]() |
8d0f1e7db2 | ||
![]() |
ac3a6aaa8c | ||
![]() |
a8b68dc4f9 | ||
![]() |
a2d2b7842d | ||
![]() |
ee9540e137 | ||
![]() |
ef1c8c55f8 | ||
![]() |
ebacc15e72 | ||
![]() |
e54ec3ba05 | ||
![]() |
fe6786aa6a | ||
![]() |
7e58bfe01d | ||
![]() |
f3edec1191 | ||
![]() |
432133a12a | ||
![]() |
bc89b63fc6 | ||
![]() |
47286fbe2a | ||
![]() |
b9823791f7 | ||
![]() |
704ffe391a | ||
![]() |
9b198e8d67 | ||
![]() |
e7f832a82f | ||
![]() |
3bcd2b6f71 | ||
![]() |
b7f596a71e | ||
![]() |
5bbddb5b26 | ||
![]() |
e5e6dda04f | ||
![]() |
70ed838571 | ||
![]() |
e564af0b5b | ||
![]() |
3596eb39f2 | ||
![]() |
eda68f127c | ||
![]() |
68d75a879b | ||
![]() |
ceded35a82 | ||
![]() |
a19e10c57a | ||
![]() |
b4237be609 | ||
![]() |
e08ee282ab | ||
![]() |
2ee5b0a9c1 | ||
![]() |
48f5ffa0bd | ||
![]() |
b01d04c4ca | ||
![]() |
94f3a085ed | ||
![]() |
59daab9434 | ||
![]() |
af88a78aae | ||
![]() |
837c3d3c9d | ||
![]() |
d952a2b756 | ||
![]() |
c07c6ca413 | ||
![]() |
8bc62f3678 | ||
![]() |
1c252634b7 | ||
![]() |
29d87646dd | ||
![]() |
8466682b65 | ||
![]() |
953f6bad46 | ||
![]() |
373a1cabe6 | ||
![]() |
988bc8b35f | ||
![]() |
0ca19133d9 | ||
![]() |
ea6ec42bbd | ||
![]() |
e9e17122e7 | ||
![]() |
f886ea9e3d | ||
![]() |
f71816d328 | ||
![]() |
0a16ae6482 | ||
![]() |
13b6fe2bba | ||
![]() |
088558b8df | ||
![]() |
9a32e28574 | ||
![]() |
e320c3b735 | ||
![]() |
ef751c0961 | ||
![]() |
52b745b8a9 | ||
![]() |
abcfbf790b | ||
![]() |
67a7b28c84 | ||
![]() |
4ca7b8569b | ||
![]() |
c63cd63c1b | ||
![]() |
3fba4274f5 | ||
![]() |
6028953eca | ||
![]() |
0e6d54ea60 | ||
![]() |
5274b03dc2 | ||
![]() |
b65583084b | ||
![]() |
66a8edb11e | ||
![]() |
8895752837 | ||
![]() |
a19b43a304 | ||
![]() |
2b00d28af9 | ||
![]() |
57b7559832 | ||
![]() |
3261a904da | ||
![]() |
b8f837365c | ||
![]() |
8837ed35cd | ||
![]() |
35533407fe | ||
![]() |
1d41f024cf | ||
![]() |
2f4aa35ca6 | ||
![]() |
6977425d04 | ||
![]() |
445743930b | ||
![]() |
f6435affe9 | ||
![]() |
c011f3fa95 | ||
![]() |
c64eec3238 | ||
![]() |
35cfc80dd7 | ||
![]() |
a42736e437 | ||
![]() |
4a63b83caa | ||
![]() |
4cb118ca29 | ||
![]() |
6ddc6a44a2 | ||
![]() |
9cd8f66e14 | ||
![]() |
b3b9c52df2 | ||
![]() |
c3afe39ea0 | ||
![]() |
f09f7feb94 | ||
![]() |
203c556ba3 | ||
![]() |
e30acfbfee | ||
![]() |
0c12af347e | ||
![]() |
318096be79 | ||
![]() |
25bfaf6c0d | ||
![]() |
0fbeb3bf7b | ||
![]() |
b6aa29012e | ||
![]() |
9fdab64e8b | ||
![]() |
82c61fb6a7 | ||
![]() |
2d429ea678 | ||
![]() |
7be494f845 | ||
![]() |
1c8e8419b6 | ||
![]() |
da7f206414 | ||
![]() |
6bd72c3ff5 | ||
![]() |
82c137d69b | ||
![]() |
a404c51797 | ||
![]() |
ff39cd753c | ||
![]() |
fe056f518e | ||
![]() |
0ebeb161e1 | ||
![]() |
f953454374 | ||
![]() |
016834185a | ||
![]() |
34c0e0f58d | ||
![]() |
95e6969912 | ||
![]() |
297e5300b4 | ||
![]() |
6cccd87318 | ||
![]() |
532c624d01 | ||
![]() |
ed17a81f50 | ||
![]() |
44be190378 | ||
![]() |
b1ac920505 | ||
![]() |
1901cc962e | ||
![]() |
babaf48867 | ||
![]() |
b3e2426967 | ||
![]() |
f1ee7fed4c | ||
![]() |
3efda8d1d2 | ||
![]() |
a5f00d1db2 | ||
![]() |
371b589cb2 | ||
![]() |
4287694b42 | ||
![]() |
700b119482 | ||
![]() |
fd05a7232a | ||
![]() |
c30982c981 | ||
![]() |
ebdb34a911 | ||
![]() |
f82ca44aac | ||
![]() |
0856c7292c | ||
![]() |
6afa197586 | ||
![]() |
0a656f13eb | ||
![]() |
e06f2a89ea | ||
![]() |
c3b6675617 | ||
![]() |
0b11559031 | ||
![]() |
dc30f0e00c | ||
![]() |
73f29a6cd4 | ||
![]() |
49be073002 | ||
![]() |
e3f9818af5 | ||
![]() |
8e0bb92c79 | ||
![]() |
ebe3b5bfff | ||
![]() |
7a337ac6fb | ||
![]() |
4b58b8057d | ||
![]() |
d694c1f548 | ||
![]() |
c77c0e4780 | ||
![]() |
62054b8433 | ||
![]() |
3880ac0b0d | ||
![]() |
6c8e0e20fb | ||
![]() |
6a7caad8dc | ||
![]() |
9c1eb78a0f | ||
![]() |
223000a9fb | ||
![]() |
9f5cd5547b | ||
![]() |
27c5594cda | ||
![]() |
ccff7f97cb | ||
![]() |
40d003eccf | ||
![]() |
784af5ad10 | ||
![]() |
c7f48e9ea3 | ||
![]() |
7c61caf68e | ||
![]() |
c2d20c548f | ||
![]() |
7876cdb37a | ||
![]() |
df9634a41f | ||
![]() |
c6a48d3b61 | ||
![]() |
5ebce075a1 | ||
![]() |
72a7f69a08 | ||
![]() |
06a133c3e9 | ||
![]() |
511ea09c99 | ||
![]() |
75659ff787 | ||
![]() |
a40d853682 | ||
![]() |
fb7fb0ea78 | ||
![]() |
6e8e4eedb5 | ||
![]() |
0400754270 | ||
![]() |
1ed8e41e90 | ||
![]() |
f837da6fe3 | ||
![]() |
7029345b9d | ||
![]() |
f0f817c361 | ||
![]() |
d82b97fbe1 | ||
![]() |
02a19d0123 | ||
![]() |
2f9afd3a2c | ||
![]() |
430275ac88 | ||
![]() |
8bff25fedd | ||
![]() |
d5741a5ba4 | ||
![]() |
0582bf7746 | ||
![]() |
50b727ba83 | ||
![]() |
8ad7b68c9e | ||
![]() |
f34455b6c2 | ||
![]() |
b3691d5d90 | ||
![]() |
7c344fa0cd | ||
![]() |
5e90a4d000 | ||
![]() |
f78391ce2a | ||
![]() |
bfbaa1e8bb | ||
![]() |
663245c351 | ||
![]() |
447446c565 | ||
![]() |
1d7754f160 | ||
![]() |
31ece55c57 | ||
![]() |
3d6434be75 | ||
![]() |
c13fbf795d | ||
![]() |
2a4d7dc561 | ||
![]() |
8b9c757fdc | ||
![]() |
2ef3dfb673 | ||
![]() |
4aa9b72739 | ||
![]() |
7cebfa75fc | ||
![]() |
a0df6ccb81 | ||
![]() |
37e51aa166 | ||
![]() |
8d3e4b6b3f | ||
![]() |
587e3f1eb2 | ||
![]() |
432911c994 | ||
![]() |
83b0954e58 | ||
![]() |
45288431f9 | ||
![]() |
0c077685b6 | ||
![]() |
4f5d3b4035 | ||
![]() |
167490b71c | ||
![]() |
5dcaeebdac | ||
![]() |
ddbadb1e26 | ||
![]() |
cf81a5c09a | ||
![]() |
a8b6464d7f | ||
![]() |
85ae63c656 | ||
![]() |
68cc34df6f | ||
![]() |
9955e7e5e1 | ||
![]() |
ab8ef1c9e1 | ||
![]() |
7e6d64a24c | ||
![]() |
e582caccc9 | ||
![]() |
1eb8035122 | ||
![]() |
57b7ed6a07 | ||
![]() |
d35f06ac15 | ||
![]() |
a50f121011 | ||
![]() |
a9168c04fd | ||
![]() |
6b317ced17 | ||
![]() |
e300cf3747 | ||
![]() |
b088830382 | ||
![]() |
7de1fe7416 | ||
![]() |
711ca6aff5 | ||
![]() |
0c8b530aa2 | ||
![]() |
467a001e1f | ||
![]() |
9bd28306f6 | ||
![]() |
5832184304 | ||
![]() |
b175adae53 | ||
![]() |
399661a7f4 | ||
![]() |
e330468a13 | ||
![]() |
f563068ce6 | ||
![]() |
94dfb66824 | ||
![]() |
052e8f0983 | ||
![]() |
62c4e072f5 | ||
![]() |
cf89b8764b | ||
![]() |
1ba098508c | ||
![]() |
46b86f4a2f | ||
![]() |
b25bb78916 | ||
![]() |
2858c8dcc7 | ||
![]() |
7f072a5ca8 | ||
![]() |
bf741c1b26 | ||
![]() |
2df709c7d0 | ||
![]() |
e9b355bd8a | ||
![]() |
ef279b125d | ||
![]() |
152b380a2f | ||
![]() |
8a39bea761 | ||
![]() |
d37fe1fbb6 | ||
![]() |
33b56b0cf9 | ||
![]() |
0383030266 | ||
![]() |
b8fe0c6c3a | ||
![]() |
7cb0c98c03 | ||
![]() |
3612df91e1 | ||
![]() |
0a0d44a0b5 | ||
![]() |
2f7b6bfa2d | ||
![]() |
27f11a1022 | ||
![]() |
ddbcfe83dd | ||
![]() |
976d8f7abe | ||
![]() |
ff3fd63eea | ||
![]() |
4cd876f159 | ||
![]() |
3f514da285 | ||
![]() |
2d9019d4b2 | ||
![]() |
d0a5feda44 | ||
![]() |
ed4ab403de | ||
![]() |
4efefd7fba | ||
![]() |
689f1519c0 | ||
![]() |
100d2369d5 | ||
![]() |
0a0a8fc67d | ||
![]() |
1887f11ec9 | ||
![]() |
e9abb357e4 | ||
![]() |
58c6702080 | ||
![]() |
f77b3d4714 | ||
![]() |
f5aee6b886 | ||
![]() |
6f26722f69 | ||
![]() |
13cfd1bae1 | ||
![]() |
5271a3eb1e | ||
![]() |
78022bf145 | ||
![]() |
99a57f5a4e | ||
![]() |
2489a6c6ef | ||
![]() |
44952a94cf | ||
![]() |
95e998d25a | ||
![]() |
30de984827 | ||
![]() |
0bb8a49ea2 | ||
![]() |
a82421306f | ||
![]() |
b4d29653c6 | ||
![]() |
70173488a8 | ||
![]() |
271ffac4a9 | ||
![]() |
f6584c1866 | ||
![]() |
00093faae2 | ||
![]() |
a9e220c96b | ||
![]() |
f7d7765d5e | ||
![]() |
9ffcf35b23 | ||
![]() |
d3a59652bb | ||
![]() |
c62a6cd779 | ||
![]() |
a2cf09fb54 | ||
![]() |
f83f3c927a | ||
![]() |
5ea04d64f6 | ||
![]() |
540b925659 | ||
![]() |
2b7e735e3d | ||
![]() |
d25192d8c5 | ||
![]() |
f1169120ae | ||
![]() |
b28dbe20b6 | ||
![]() |
8dde59be02 | ||
![]() |
abca177894 | ||
![]() |
d3bb2e5e16 | ||
![]() |
7f8a89838b | ||
![]() |
39c4b338f1 | ||
![]() |
4518335a56 | ||
![]() |
b856b0e15d | ||
![]() |
5d518b5365 | ||
![]() |
ce86112612 | ||
![]() |
ff0562ad1e | ||
![]() |
80764261c3 | ||
![]() |
b515480a98 | ||
![]() |
9309297d76 | ||
![]() |
16e0ed9242 | ||
![]() |
d650bcca3b | ||
![]() |
a13c4d4c17 | ||
![]() |
f28b7f2187 | ||
![]() |
413263a6eb | ||
![]() |
66bb6a6ffa | ||
![]() |
000d2047fb | ||
![]() |
90f5b178ef | ||
![]() |
a71a4d642b | ||
![]() |
f651b1f54b | ||
![]() |
74cef6966d | ||
![]() |
749d3c360a | ||
![]() |
5a12056e59 | ||
![]() |
db582bdc1b | ||
![]() |
59d610af17 | ||
![]() |
c8d5500441 | ||
![]() |
56ba4907e1 | ||
![]() |
4fbd4957bd | ||
![]() |
b116e58620 | ||
![]() |
e095120023 | ||
![]() |
3ef3d848f7 | ||
![]() |
610a327b52 | ||
![]() |
81436fb688 | ||
![]() |
24fe9cdd5a | ||
![]() |
e5c499c22e | ||
![]() |
99a8604601 | ||
![]() |
3ef821d62f | ||
![]() |
a38e047e83 | ||
![]() |
e0fcf9b648 | ||
![]() |
0e823b566b | ||
![]() |
a9d24c2cd5 | ||
![]() |
7a7cad39eb | ||
![]() |
1a76a953c7 | ||
![]() |
db27079fa8 | ||
![]() |
272d36bc93 | ||
![]() |
487b56ab69 | ||
![]() |
fffc7e2e8e | ||
![]() |
5d0fa1417e | ||
![]() |
8236394b85 | ||
![]() |
2ea604cc2a | ||
![]() |
8d687c951a | ||
![]() |
11319ac479 | ||
![]() |
903afb62d0 | ||
![]() |
938e06c00e | ||
![]() |
d0f4b23063 | ||
![]() |
cb0452d80e | ||
![]() |
bdaea7879b | ||
![]() |
0f3a2f1f29 | ||
![]() |
949bd8d738 | ||
![]() |
7adec2d894 | ||
![]() |
cacbb2eb12 | ||
![]() |
15281f468e | ||
![]() |
3ba18550cd | ||
![]() |
e90a9940d4 | ||
![]() |
09d437d531 | ||
![]() |
f1cc5182f0 | ||
![]() |
d26160c755 | ||
![]() |
224fd24898 | ||
![]() |
1e5186fe94 | ||
![]() |
6e6d6c65ef | ||
![]() |
3881e0cb23 | ||
![]() |
eb0af3752c | ||
![]() |
2e1dbe51a4 | ||
![]() |
c19b5c5ac3 | ||
![]() |
ad1a71ebc3 | ||
![]() |
aad6a24f28 | ||
![]() |
bda66d1929 | ||
![]() |
2ff3c74fab | ||
![]() |
056e712667 | ||
![]() |
9acceda0f8 | ||
![]() |
9511103e26 | ||
![]() |
ae8c9d82bc | ||
![]() |
7b016063ca | ||
![]() |
00acb180d6 | ||
![]() |
46f9c0fb8a | ||
![]() |
ef1649383c | ||
![]() |
afde5a7ece | ||
![]() |
30b8565548 | ||
![]() |
a971b92899 | ||
![]() |
4ee7cdc8a0 | ||
![]() |
4c2788a13c | ||
![]() |
8b4e193614 | ||
![]() |
f0ce65af7d | ||
![]() |
b81c61dd99 | ||
![]() |
30ef7a5e88 | ||
![]() |
cd26384634 | ||
![]() |
1f8c1f151d | ||
![]() |
36ce8ba79e | ||
![]() |
c32f698671 | ||
![]() |
17efa1bda5 | ||
![]() |
da19854520 | ||
![]() |
fc1fb0ab7c | ||
![]() |
f3d50e2104 | ||
![]() |
621526bbae | ||
![]() |
ceeea52915 | ||
![]() |
ff4bb962c4 | ||
![]() |
84578f515d | ||
![]() |
5a6492b76d | ||
![]() |
11d74124cd | ||
![]() |
b19fe17e76 | ||
![]() |
47326b2295 | ||
![]() |
951c373110 | ||
![]() |
b9b76b3519 | ||
![]() |
da6885af6c | ||
![]() |
bc2173747c | ||
![]() |
d0e6b3e268 | ||
![]() |
1d12d4d54c | ||
![]() |
eac9c3c4f2 | ||
![]() |
e3c51f0350 | ||
![]() |
bab4ad4f17 | ||
![]() |
b05c88f1bc | ||
![]() |
13df452dd4 | ||
![]() |
285408b46c | ||
![]() |
e55035b2f9 | ||
![]() |
02cb592917 | ||
![]() |
ca26c8bbd7 | ||
![]() |
b0ba0e77f8 | ||
![]() |
827711bcd1 | ||
![]() |
3d4ef8cfe1 | ||
![]() |
6751a38b8e | ||
![]() |
18e9e262e4 | ||
![]() |
cee96ae207 | ||
![]() |
4c0f075d6a | ||
![]() |
6b966e2c47 | ||
![]() |
1bb5d4754f | ||
![]() |
172a02a605 | ||
![]() |
b6f868f629 | ||
![]() |
5697f4b4e7 | ||
![]() |
30f9e1b479 | ||
![]() |
fcbcebea9b | ||
![]() |
f81606cbf5 | ||
![]() |
3240be0bb6 | ||
![]() |
18be6cbadc | ||
![]() |
cf6b84790f | ||
![]() |
aaa8083d49 | ||
![]() |
e746965b1c | ||
![]() |
3dda76115c | ||
![]() |
fbf0e69558 | ||
![]() |
ee6945d63d | ||
![]() |
824f551969 | ||
![]() |
f93c0c5cd3 | ||
![]() |
a6d3ee90f0 | ||
![]() |
9f08955fef | ||
![]() |
ac2e290d97 | ||
![]() |
ee5c1ea3f7 | ||
![]() |
4e10895a19 | ||
![]() |
9b49ca3820 | ||
![]() |
719aa0f317 | ||
![]() |
50c573eb4d | ||
![]() |
f1cb8e80b3 | ||
![]() |
988a467afd | ||
![]() |
741487a1fc | ||
![]() |
9b29d09d45 | ||
![]() |
062ac5f27d | ||
![]() |
a002e9b12f | ||
![]() |
db64a9ebfa | ||
![]() |
3fbde22cc4 | ||
![]() |
758e60a58d | ||
![]() |
5201410e39 | ||
![]() |
b1b7944012 | ||
![]() |
8ef04268be | ||
![]() |
b107e87d38 | ||
![]() |
b0b9579778 | ||
![]() |
7eade4029a | ||
![]() |
3d4913348a | ||
![]() |
1720b71d62 | ||
![]() |
c2a9a39ee0 | ||
![]() |
f59e727f16 | ||
![]() |
8ea8969d80 | ||
![]() |
e96fed20c8 | ||
![]() |
e208aac834 | ||
![]() |
101b5b3b35 | ||
![]() |
5117a16841 | ||
![]() |
9389a7c9be | ||
![]() |
487a74ba5d | ||
![]() |
39d441a29b | ||
![]() |
bf1ad0a757 | ||
![]() |
cfc020daa2 | ||
![]() |
4ee5a29bc0 | ||
![]() |
b66aaeea99 | ||
![]() |
589086f0d0 | ||
![]() |
6f8060dea7 | ||
![]() |
b8ef87d84c | ||
![]() |
7370b0ffc6 | ||
![]() |
209cf44e8e | ||
![]() |
b7dacabbe4 | ||
![]() |
5098c35814 | ||
![]() |
896df60f32 | ||
![]() |
b26ab2849b | ||
![]() |
36f52a26f6 | ||
![]() |
f0295d562d | ||
![]() |
081bd22e59 | ||
![]() |
668c73010a | ||
![]() |
fe371f0438 | ||
![]() |
be28dc0bca | ||
![]() |
4578baca3e | ||
![]() |
4d6e694d14 | ||
![]() |
fd8a4182d9 | ||
![]() |
bedc1e5672 | ||
![]() |
047dc19351 | ||
![]() |
fb31b04c08 | ||
![]() |
aa9dff572e | ||
![]() |
b5005430be | ||
![]() |
40bcd38caa | ||
![]() |
68e2824a28 | ||
![]() |
0cce35b23e | ||
![]() |
162c39258e | ||
![]() |
14f7f5ba45 | ||
![]() |
35a9106a4b | ||
![]() |
b49e6243d1 | ||
![]() |
bb661ad083 | ||
![]() |
7b3369b71d | ||
![]() |
c9f87afd8b | ||
![]() |
8648d8d012 | ||
![]() |
a6a011ec19 | ||
![]() |
b57f97b954 | ||
![]() |
b70df4ab18 | ||
![]() |
6e79d49c80 | ||
![]() |
1f75f61bb0 | ||
![]() |
1a12611117 | ||
![]() |
0e11c10468 | ||
![]() |
c06b18b47b | ||
![]() |
94b4824c27 | ||
![]() |
a918981ff3 | ||
![]() |
6d7dfc0804 | ||
![]() |
c5cf95c14b | ||
![]() |
f79ce7bd04 | ||
![]() |
578c1b283a | ||
![]() |
5ae0844f35 | ||
![]() |
8e3e2d436e | ||
![]() |
4af6804c50 | ||
![]() |
9c40b511f2 | ||
![]() |
e6bc48ab68 | ||
![]() |
9358b5089e | ||
![]() |
b7ad83c655 | ||
![]() |
b0b0b15d9d | ||
![]() |
5fd059a3b6 | ||
![]() |
1f000e2c3e | ||
![]() |
1333e23c23 | ||
![]() |
b572c0df7f | ||
![]() |
139a0ca008 | ||
![]() |
0458b5e3a6 | ||
![]() |
c91c9f2b40 | ||
![]() |
5165d746aa | ||
![]() |
74219663d6 | ||
![]() |
be04f14a78 | ||
![]() |
4f342eae27 | ||
![]() |
8185ddf9a1 | ||
![]() |
90892d275c | ||
![]() |
1c4951a8d7 | ||
![]() |
95a33ba894 | ||
![]() |
748e2696dc | ||
![]() |
6cadc5b157 | ||
![]() |
d32e3dc31a | ||
![]() |
807bfb71df | ||
![]() |
c2f16cf21d | ||
![]() |
a45f5c7831 | ||
![]() |
9aba1985c7 | ||
![]() |
066a418518 | ||
![]() |
9ca7efbe4c | ||
![]() |
a5dec53e1b | ||
![]() |
f1de903fb5 | ||
![]() |
fa07787007 | ||
![]() |
0d27e10d77 | ||
![]() |
8dee5f4cf8 | ||
![]() |
c6a7350db1 | ||
![]() |
2a68952334 | ||
![]() |
7f801faed1 | ||
![]() |
02600bf190 | ||
![]() |
f41d283354 | ||
![]() |
f34e831650 | ||
![]() |
c9ec533aa5 | ||
![]() |
2a879afc7a | ||
![]() |
71c2557405 | ||
![]() |
214fc04473 | ||
![]() |
8adfcf23f0 | ||
![]() |
4bbd69955b | ||
![]() |
0507ec9d8b | ||
![]() |
586d7eaba6 | ||
![]() |
f075823529 | ||
![]() |
a695dc20fd | ||
![]() |
8e4710a2a9 | ||
![]() |
c6cba5ebc8 | ||
![]() |
63aa46369b | ||
![]() |
5bcffba53e | ||
![]() |
1e2741ff1b | ||
![]() |
973524a4e6 | ||
![]() |
fa1a53cdeb | ||
![]() |
401002dcd4 | ||
![]() |
c68056d3ad | ||
![]() |
0c8630a2f0 | ||
![]() |
a495946eeb | ||
![]() |
bb9ea7ce6e | ||
![]() |
07d5af1969 | ||
![]() |
7756038bee | ||
![]() |
38834d1945 | ||
![]() |
c3ee79e4db | ||
![]() |
72b392e853 | ||
![]() |
6f43285a28 | ||
![]() |
d0e44893f5 | ||
![]() |
be8aa16170 | ||
![]() |
36a1877cbd | ||
![]() |
78dbd090b5 | ||
![]() |
4b01ab616a | ||
![]() |
ef8cdf0405 | ||
![]() |
c11b88b4c2 | ||
![]() |
84992da24a | ||
![]() |
5e83feeabf | ||
![]() |
ae5d8f4d64 | ||
![]() |
90d574e521 | ||
![]() |
fc2cddc452 | ||
![]() |
7c86fa0203 | ||
![]() |
8c96eb7c56 | ||
![]() |
4b84b74b89 | ||
![]() |
8a3279a5c9 | ||
![]() |
7c56ee8e0c | ||
![]() |
007873153e | ||
![]() |
f6aa3e0cdc | ||
![]() |
b07628ae57 | ||
![]() |
90c6e1c449 | ||
![]() |
5b5b57b810 | ||
![]() |
21dbce1554 | ||
![]() |
72300a54df | ||
![]() |
2bd2dcb50a | ||
![]() |
2e6cd4f12b | ||
![]() |
12cc158b64 | ||
![]() |
cd0195a27a | ||
![]() |
863b63d75e | ||
![]() |
3a36a789ad | ||
![]() |
d0af3339fc | ||
![]() |
c74f187b1f | ||
![]() |
4779916ac4 | ||
![]() |
1a78d96014 | ||
![]() |
1ec3446c56 | ||
![]() |
165dd351b7 | ||
![]() |
8eed7110a1 | ||
![]() |
41abc08d63 | ||
![]() |
251d8919ea | ||
![]() |
19818d96b7 | ||
![]() |
f828cdcaef | ||
![]() |
dd00cfc7a2 | ||
![]() |
e649e27d4d | ||
![]() |
61e8ab1300 | ||
![]() |
e52a303e93 | ||
![]() |
f2d21ea735 | ||
![]() |
8af64456ec | ||
![]() |
c9a4deb118 | ||
![]() |
878347243d | ||
![]() |
d7e471e244 | ||
![]() |
f29154011e | ||
![]() |
af47a94e70 | ||
![]() |
a3c45a6f89 | ||
![]() |
da9b077c11 | ||
![]() |
f298281ec4 | ||
![]() |
df8daf561e | ||
![]() |
13a6aaa6ff | ||
![]() |
405311e89f | ||
![]() |
36632f64f1 | ||
![]() |
3b88452b2f | ||
![]() |
2f0138e891 | ||
![]() |
f584e3f689 | ||
![]() |
1fffa748e5 | ||
![]() |
74fea6d306 | ||
![]() |
b6630a48b2 | ||
![]() |
29c1bec0f3 | ||
![]() |
958c9c08d6 | ||
![]() |
d2b1918e9c | ||
![]() |
cdc93d7110 | ||
![]() |
b860caa631 | ||
![]() |
52c09396e0 | ||
![]() |
3022fc4702 | ||
![]() |
8567fe94e1 | ||
![]() |
3565fec005 | ||
![]() |
7be5ef8b6c | ||
![]() |
2183ff5906 | ||
![]() |
b0192cf9c0 | ||
![]() |
1e770f089d | ||
![]() |
8b4847162d | ||
![]() |
706f1f8a66 | ||
![]() |
ab2d171909 | ||
![]() |
0d3396ed64 | ||
![]() |
01bac9f433 | ||
![]() |
1cb60dd5c7 | ||
![]() |
4885b22cb4 | ||
![]() |
1fb70625a3 | ||
![]() |
ad6e8b2d62 | ||
![]() |
9b23d7c2fd | ||
![]() |
7f7a0003c7 | ||
![]() |
767be18265 | ||
![]() |
84944cfc24 | ||
![]() |
08d5175d05 | ||
![]() |
05e15dc318 | ||
![]() |
f1ee11cb14 | ||
![]() |
f2b3e63ff6 | ||
![]() |
f01a0f9151 | ||
![]() |
ebc31c0f08 | ||
![]() |
55040cfde5 | ||
![]() |
0b7576b634 | ||
![]() |
a096c20930 | ||
![]() |
fa1b8c824c | ||
![]() |
f207d46390 | ||
![]() |
08d93b8349 | ||
![]() |
60c7a91794 | ||
![]() |
ad3e520e09 | ||
![]() |
8fd9f56d21 | ||
![]() |
dd7f282723 | ||
![]() |
fdb737d1d9 | ||
![]() |
ed3e04b9ed | ||
![]() |
eb7742ea7c | ||
![]() |
48cfbf8662 | ||
![]() |
1034e4ec50 | ||
![]() |
bfd6989c75 | ||
![]() |
353b40b28a | ||
![]() |
da82d171e0 | ||
![]() |
f6a3eea7f2 | ||
![]() |
d0120d5e0a | ||
![]() |
77f5fb765b | ||
![]() |
a87fedc0af | ||
![]() |
c1b8497aaa | ||
![]() |
35e84d0427 | ||
![]() |
a9cc882394 | ||
![]() |
17b4c1a2ca | ||
![]() |
a0663d84d2 | ||
![]() |
bde0bdbf80 | ||
![]() |
d128443a2a | ||
![]() |
8818a5ab6c | ||
![]() |
9baa7c6c24 | ||
![]() |
fbbfd46fb8 | ||
![]() |
4ebcbadfc2 | ||
![]() |
e288246366 | ||
![]() |
4dee2b599a | ||
![]() |
77c6a48553 | ||
![]() |
948ec80b6e | ||
![]() |
8ca9724258 | ||
![]() |
1c90bdddb4 | ||
![]() |
0cba7acf5a | ||
![]() |
7e50a4999c | ||
![]() |
6d1ba10788 | ||
![]() |
f2f68859cc | ||
![]() |
aecd74c6af | ||
![]() |
226406b853 | ||
![]() |
d66bc6a873 | ||
![]() |
49daf57c54 | ||
![]() |
65e53b8251 | ||
![]() |
56e76a3265 | ||
![]() |
93555fed75 | ||
![]() |
65b227126d | ||
![]() |
661b593db3 | ||
![]() |
a778690b64 | ||
![]() |
2d2efeb9bb | ||
![]() |
cb1cf2238d | ||
![]() |
97602a127a | ||
![]() |
e3354895f8 | ||
![]() |
5fafaa3c4f | ||
![]() |
7b3182fa8f | ||
![]() |
04c849b0ee | ||
![]() |
dfa6f0223a | ||
![]() |
45c28dd9c5 | ||
![]() |
70e39a26a2 | ||
![]() |
6de02fc1b9 | ||
![]() |
24f63127de | ||
![]() |
0892acbabd | ||
![]() |
ec6a1f9137 | ||
![]() |
7ff633f531 | ||
![]() |
9f5baa0bf7 | ||
![]() |
78b0837cb8 | ||
![]() |
d5bcafaefd | ||
![]() |
4486251382 | ||
![]() |
603707aa85 | ||
![]() |
4c6960ed36 | ||
![]() |
e55a014e94 | ||
![]() |
3e9963a216 | ||
![]() |
557684c3ce | ||
![]() |
225becc89a | ||
![]() |
07f2f78b02 | ||
![]() |
acfb4e462e | ||
![]() |
e921f72d31 | ||
![]() |
5ce62c8446 | ||
![]() |
10606360f7 | ||
![]() |
1eda3d31f9 | ||
![]() |
064d115ccb | ||
![]() |
c6805aa354 | ||
![]() |
cf4b6307ae | ||
![]() |
762537d82d | ||
![]() |
352995c663 | ||
![]() |
151c0d9761 | ||
![]() |
aa476b392c | ||
![]() |
963651d6f2 | ||
![]() |
32094c8773 | ||
![]() |
dde0dab3db | ||
![]() |
b541abc551 | ||
![]() |
69b3da48b1 | ||
![]() |
762d7357b5 | ||
![]() |
99d830551a | ||
![]() |
a77e09b2c2 | ||
![]() |
8d68963854 | ||
![]() |
60d1606049 | ||
![]() |
3fe8afe667 | ||
![]() |
4828d3d85b | ||
![]() |
11e4ad2272 | ||
![]() |
d8b4fa4a8b | ||
![]() |
72fe4db937 | ||
![]() |
5de1d04b6e | ||
![]() |
7e87181826 | ||
![]() |
45a927ffb2 | ||
![]() |
3ab6663434 | ||
![]() |
7062838940 | ||
![]() |
4d637e5f30 | ||
![]() |
f187091594 | ||
![]() |
84205a9a57 | ||
![]() |
bba8b8e759 | ||
![]() |
190611a079 | ||
![]() |
00eb23b43f | ||
![]() |
97e1be98df | ||
![]() |
09efbc569f | ||
![]() |
a1678368cf | ||
![]() |
4688171ce0 | ||
![]() |
b71cbd2033 | ||
![]() |
e1c7c3fdb2 | ||
![]() |
2856915b6d | ||
![]() |
75153dd4a3 | ||
![]() |
f7e6b060a7 | ||
![]() |
159f6750d7 | ||
![]() |
e707b50658 | ||
![]() |
4bbc737954 | ||
![]() |
25f9560fb6 | ||
![]() |
705b253a99 | ||
![]() |
56057a638f | ||
![]() |
863c7414bc | ||
![]() |
65a9e18b27 | ||
![]() |
56ddbd87b2 | ||
![]() |
9ec870c750 | ||
![]() |
b57f33c41a | ||
![]() |
ab0b0dc51c | ||
![]() |
1fbb158211 | ||
![]() |
c4f5a05b27 | ||
![]() |
80910b4f9a | ||
![]() |
9d1045dd7a | ||
![]() |
9f4d4862b4 | ||
![]() |
2b78d5235d | ||
![]() |
e5b360cd08 | ||
![]() |
692ed8c639 | ||
![]() |
773860ca5c | ||
![]() |
953626b2d4 | ||
![]() |
bd7682a694 | ||
![]() |
8b893173fd | ||
![]() |
17734d54ab | ||
![]() |
d3b845c01a | ||
![]() |
d9c9adbc91 | ||
![]() |
cceaa088cb | ||
![]() |
225743a620 | ||
![]() |
42818c150f | ||
![]() |
7bed868d60 | ||
![]() |
ce1ef73366 | ||
![]() |
77fe206084 | ||
![]() |
22b8d43bf5 | ||
![]() |
e701001c5f | ||
![]() |
1e97ca14f1 | ||
![]() |
e984801104 | ||
![]() |
0a389a4651 | ||
![]() |
70c241b51b | ||
![]() |
4a21b1f589 | ||
![]() |
a1d48ad1ec | ||
![]() |
baf5750425 | ||
![]() |
186c13f1ab | ||
![]() |
16a0bd7ff3 | ||
![]() |
152b6c2d1a | ||
![]() |
29c1f873eb | ||
![]() |
64513c8c9a | ||
![]() |
4294d10789 | ||
![]() |
be489e83a1 | ||
![]() |
5dfb043896 | ||
![]() |
5a7f1d62c1 | ||
![]() |
3d1ff5b8d0 | ||
![]() |
ab7b42c022 | ||
![]() |
854e33025b | ||
![]() |
b3ec3d0baf | ||
![]() |
108e2ec1ba | ||
![]() |
4425c3aea2 | ||
![]() |
0f5733ac59 | ||
![]() |
21f1875816 | ||
![]() |
2525d319a3 | ||
![]() |
4e876cb473 | ||
![]() |
a4f475245c | ||
![]() |
f7d1cfb625 | ||
![]() |
ba75856f2b | ||
![]() |
b4db9f615d | ||
![]() |
c0c6a457bd | ||
![]() |
0cffba77cf | ||
![]() |
4aa8b6cad8 | ||
![]() |
ef13da5555 | ||
![]() |
f8712b0e00 | ||
![]() |
87425d4ab1 | ||
![]() |
dda4cf4d58 | ||
![]() |
ad0d3b4848 | ||
![]() |
904f5c4346 | ||
![]() |
800cf6c8c0 | ||
![]() |
79252c06b2 | ||
![]() |
867d5088e3 | ||
![]() |
7469f57a7b | ||
![]() |
54ef16f01a | ||
![]() |
22a123fd4b | ||
![]() |
a9b611d3ed | ||
![]() |
8302a7879e | ||
![]() |
b882304ec2 | ||
![]() |
6ae9399237 | ||
![]() |
1bf2c4d976 | ||
![]() |
67de1d3466 | ||
![]() |
4682de5ac1 | ||
![]() |
6348f130bc | ||
![]() |
989a040b67 | ||
![]() |
16ad8cf720 | ||
![]() |
755ddf1a94 | ||
![]() |
d587f134ca | ||
![]() |
c163d4a4b5 | ||
![]() |
94c474eab2 | ||
![]() |
5658a1efec | ||
![]() |
b315df2118 | ||
![]() |
92c06f0818 | ||
![]() |
a99efcb5c2 | ||
![]() |
57848cdf35 | ||
![]() |
85869be2d8 | ||
![]() |
33a05541a4 | ||
![]() |
3377f6b12a | ||
![]() |
4b8217777e | ||
![]() |
d9f3bdea53 | ||
![]() |
4b5d0915a9 | ||
![]() |
d2195e2b37 | ||
![]() |
e6141ae558 | ||
![]() |
5217139e0b | ||
![]() |
414a59ae9f | ||
![]() |
400741006b | ||
![]() |
2109444ba5 | ||
![]() |
f8704a2dfc | ||
![]() |
7c191388a9 | ||
![]() |
b4bac0f7a0 | ||
![]() |
d768fd4de9 | ||
![]() |
ab90ea7884 | ||
![]() |
98db0a2d2e | ||
![]() |
f914625b8a | ||
![]() |
b5c2c9ec9b | ||
![]() |
77490287e9 | ||
![]() |
f449620d38 | ||
![]() |
0db5bb27a8 | ||
![]() |
526c418e1e | ||
![]() |
637fdf72ca | ||
![]() |
b14af3e727 | ||
![]() |
24db31fa28 | ||
![]() |
a83c778c4f | ||
![]() |
68ba1d8790 | ||
![]() |
ca05f8928d | ||
![]() |
b1444ffefb | ||
![]() |
f4f8aa3e52 | ||
![]() |
90ac426a54 | ||
![]() |
4e39a00b3d | ||
![]() |
c2365b8c0f | ||
![]() |
c8d49a8adf | ||
![]() |
27f3c0a302 | ||
![]() |
98993d8503 | ||
![]() |
b880c33043 | ||
![]() |
55283df705 | ||
![]() |
1c2ebdf307 | ||
![]() |
0d7eec710c | ||
![]() |
b0a2c8d430 | ||
![]() |
b759f2c7ca | ||
![]() |
e4d29bf3ec | ||
![]() |
195d4b6897 | ||
![]() |
6348884735 | ||
![]() |
1bc4de2bd3 | ||
![]() |
2e4cd5f343 | ||
![]() |
8fa1a1f600 | ||
![]() |
a2651845f3 | ||
![]() |
79f4b6eb6b | ||
![]() |
77107e4501 | ||
![]() |
9678cbdde2 | ||
![]() |
5c9a8a27c8 | ||
![]() |
715fe4eef8 | ||
![]() |
51a63c1fc4 | ||
![]() |
b47992dba0 | ||
![]() |
dc84196202 | ||
![]() |
e96d8a961c | ||
![]() |
df9de8eb5d | ||
![]() |
44118d8fb6 | ||
![]() |
4ff376cdd6 | ||
![]() |
2568932c1c | ||
![]() |
067efc7805 | ||
![]() |
e065673d7b | ||
![]() |
2a9da208d4 | ||
![]() |
eaac00acfc | ||
![]() |
215e3f2dab | ||
![]() |
5018e53b33 | ||
![]() |
758c0adb5e | ||
![]() |
810df38f0d | ||
![]() |
e109b04efe | ||
![]() |
11f121b008 | ||
![]() |
c87e03ee6f | ||
![]() |
90842fcb84 | ||
![]() |
63ebea1706 | ||
![]() |
20398cc0a6 | ||
![]() |
68c0f770fe | ||
![]() |
7bc273b182 | ||
![]() |
19cc168433 | ||
![]() |
ab6fb5cb77 | ||
![]() |
114a7226d6 | ||
![]() |
415213a325 | ||
![]() |
342e84e550 | ||
![]() |
9979e465aa | ||
![]() |
13df3bce1b | ||
![]() |
ef35eea0f6 | ||
![]() |
7d4a9ac65a | ||
![]() |
3a7620bd08 | ||
![]() |
2a1fe9d29a | ||
![]() |
d5193e64de | ||
![]() |
6b7a7939d2 | ||
![]() |
b1c0d8fb6c | ||
![]() |
bee6d87e7a | ||
![]() |
28332f23b3 | ||
![]() |
181709f3d2 | ||
![]() |
a47f73244c | ||
![]() |
fefa1a7259 | ||
![]() |
e61f7f0274 | ||
![]() |
46ab5ab38e | ||
![]() |
ca2bc9906d | ||
![]() |
6d95ee7a00 | ||
![]() |
3df67ff9e1 | ||
![]() |
71acb2c665 | ||
![]() |
e17c87ef72 | ||
![]() |
7462d140af | ||
![]() |
2e8506de80 | ||
![]() |
c3ad493bb7 | ||
![]() |
15c101e85d | ||
![]() |
9e3f7ac8df | ||
![]() |
04c1c1a279 | ||
![]() |
c86c522eb1 | ||
![]() |
7874711936 | ||
![]() |
f757e258a7 | ||
![]() |
961f36c679 | ||
![]() |
62b1f23328 | ||
![]() |
f295684c10 | ||
![]() |
1126c750e1 | ||
![]() |
d31dea50bb | ||
![]() |
2bf31dc5b3 | ||
![]() |
b68c5cec94 | ||
![]() |
42227c1c53 | ||
![]() |
3cc099af80 | ||
![]() |
dfa18b4b6a | ||
![]() |
3198233b8f | ||
![]() |
73328dab5e | ||
![]() |
9baf3ff706 | ||
![]() |
2beca3e69a | ||
![]() |
bd136fa79a | ||
![]() |
fa09a93cfe | ||
![]() |
69de68c025 | ||
![]() |
7ca8e9077a | ||
![]() |
a1845e9ef0 | ||
![]() |
1f5b948ead | ||
![]() |
644e826ca7 | ||
![]() |
41ba1dff71 | ||
![]() |
f075742a86 | ||
![]() |
3c1c6069da | ||
![]() |
cdb6161d3d | ||
![]() |
4af90e41ce | ||
![]() |
e909596587 | ||
![]() |
55c71b5e83 | ||
![]() |
e3ce699d75 | ||
![]() |
45401d4308 | ||
![]() |
18047726b6 | ||
![]() |
1b8d9f7cc4 | ||
![]() |
83b9c6188d | ||
![]() |
993088d26e | ||
![]() |
a9ffc149f8 | ||
![]() |
b0f214bd9c | ||
![]() |
7c117452ba | ||
![]() |
32db1d1eb2 | ||
![]() |
52d949ec90 | ||
![]() |
91ba8c0ef0 | ||
![]() |
ee043d8614 | ||
![]() |
4a7c181e91 | ||
![]() |
ed68b15a31 | ||
![]() |
f01634f75c | ||
![]() |
1ea21b7011 | ||
![]() |
2ec546db3d | ||
![]() |
00b05d764d | ||
![]() |
31e0ddaec5 | ||
![]() |
6fd61be276 | ||
![]() |
796d74886e | ||
![]() |
5a9246468e | ||
![]() |
7c346c2f7c | ||
![]() |
05d54a60b0 | ||
![]() |
f560256546 | ||
![]() |
7878d97588 | ||
![]() |
3cea3eb6e5 | ||
![]() |
76ead858cf | ||
![]() |
c1ed584f2d | ||
![]() |
e0e31693f5 | ||
![]() |
8500e3c5a8 | ||
![]() |
96a1c80626 | ||
![]() |
3182dac1eb | ||
![]() |
af6ca7a4d3 | ||
![]() |
a2c1f08c8c | ||
![]() |
eb4f667a1a | ||
![]() |
5db90478f3 | ||
![]() |
b4f0485be2 | ||
![]() |
e861957937 | ||
![]() |
8a9c94fd9e | ||
![]() |
5a8013b58c | ||
![]() |
8813f669c2 | ||
![]() |
f3d077c1e1 | ||
![]() |
264e340b9e | ||
![]() |
d7f54ce98f | ||
![]() |
1381b279f0 | ||
![]() |
b7ec0d4884 | ||
![]() |
da5dc1130e | ||
![]() |
d3389fa22e | ||
![]() |
ff9a4f8754 | ||
![]() |
052df518d0 | ||
![]() |
fb1c3f7f1c | ||
![]() |
c8e2af8046 | ||
![]() |
ecb7d7b992 | ||
![]() |
4f42165c8a | ||
![]() |
f1f09f7156 | ||
![]() |
53e6c7f0c4 | ||
![]() |
4371068f6a | ||
![]() |
28a9793a7b | ||
![]() |
be0f2719e2 | ||
![]() |
dc2d0b9297 | ||
![]() |
b0974d89a6 | ||
![]() |
fec4966ee0 | ||
![]() |
bb164bb32c | ||
![]() |
e626937147 | ||
![]() |
bdc5af8dd2 | ||
![]() |
5f10c55303 | ||
![]() |
96035ccd6f | ||
![]() |
3dc79aa60a | ||
![]() |
24a16ff8fe | ||
![]() |
111c2006c8 | ||
![]() |
81b4c6956b | ||
![]() |
14a3599c47 | ||
![]() |
475e70986b | ||
![]() |
d4f1fd7396 | ||
![]() |
1505343b4b | ||
![]() |
1af6c04111 | ||
![]() |
3c876c4fe1 | ||
![]() |
5d73714f5a | ||
![]() |
d2469e4159 | ||
![]() |
af9ae2e0a4 | ||
![]() |
e9f32617cc | ||
![]() |
9feae62f93 | ||
![]() |
7198a5647d | ||
![]() |
bf643b63ad | ||
![]() |
802c556e82 | ||
![]() |
4ea587804e | ||
![]() |
ca9dd0c833 | ||
![]() |
740209a81d | ||
![]() |
3d66065fe6 | ||
![]() |
68c83ea629 | ||
![]() |
7fb879f191 | ||
![]() |
79924fcc7a | ||
![]() |
5fa14aae7d | ||
![]() |
588fb283cc | ||
![]() |
48267c2705 | ||
![]() |
9ee6ae8f94 | ||
![]() |
431fe5950c | ||
![]() |
fca071742d | ||
![]() |
ab2b2f6dd5 | ||
![]() |
8d8c1335c5 | ||
![]() |
49edd91f4e | ||
![]() |
afa2d268f2 | ||
![]() |
5a4de04bcf | ||
![]() |
7071f3a966 | ||
![]() |
061d88f875 | ||
![]() |
a6236886e4 | ||
![]() |
472b12bef5 | ||
![]() |
66a5f24d4a | ||
![]() |
3c0f766933 | ||
![]() |
decf3d320b | ||
![]() |
71a03c8ca5 | ||
![]() |
037668ed80 | ||
![]() |
7d0e356560 | ||
![]() |
0f1e70ca79 | ||
![]() |
9c6b019ca9 | ||
![]() |
92adb5d58a | ||
![]() |
755761867d | ||
![]() |
a1dfa8ebc6 | ||
![]() |
1544b8cea7 | ||
![]() |
e8b7ddc966 | ||
![]() |
2485aa772c | ||
![]() |
10525c7aa7 | ||
![]() |
0c83156ba4 | ||
![]() |
0d4331829c | ||
![]() |
276874c414 | ||
![]() |
ca5368f01f | ||
![]() |
d4a7cefa8d | ||
![]() |
473d0af85d | ||
![]() |
eb16ca847a | ||
![]() |
8feb382ae5 | ||
![]() |
18eeda0e03 | ||
![]() |
caf5020bac | ||
![]() |
af5cb948a0 | ||
![]() |
68047f7c1a | ||
![]() |
70c028458f | ||
![]() |
b7275de837 | ||
![]() |
4bfcfb0017 | ||
![]() |
483d09b9c1 | ||
![]() |
4ecdb1f19f | ||
![]() |
e0c0d3b53f | ||
![]() |
91ead3be50 | ||
![]() |
5c9f29c43a | ||
![]() |
47d1920f8a | ||
![]() |
f4f614a0bc | ||
![]() |
2bc533d0cb | ||
![]() |
23510e6839 | ||
![]() |
49478298cc | ||
![]() |
2f955ccfd7 | ||
![]() |
f26a49eca5 | ||
![]() |
fceba0bb88 | ||
![]() |
72472cd11f | ||
![]() |
ee64aafc39 | ||
![]() |
18833d342e | ||
![]() |
ca5e752514 | ||
![]() |
52a9921ed3 | ||
![]() |
86aa758ecd | ||
![]() |
03676693ce | ||
![]() |
1f3b9bc70c | ||
![]() |
7343649c54 | ||
![]() |
b3571602bb | ||
![]() |
a6cec21c43 | ||
![]() |
3957337b9f | ||
![]() |
9244bf28ef | ||
![]() |
851c20aeb2 | ||
![]() |
4d50a20500 | ||
![]() |
40f31faa10 | ||
![]() |
9e21fb6b52 | ||
![]() |
991bf126d4 | ||
![]() |
15db2225da | ||
![]() |
8cf0a01149 | ||
![]() |
580e229cf2 | ||
![]() |
45526f4e8a | ||
![]() |
716fa63e73 | ||
![]() |
fbf44b37a9 | ||
![]() |
444df4a7d2 | ||
![]() |
34cb12d3c9 | ||
![]() |
d058802325 | ||
![]() |
7949357180 | ||
![]() |
e9b50706a9 | ||
![]() |
8eb6f29c53 | ||
![]() |
e3f10f977b | ||
![]() |
f33d120ebf | ||
![]() |
c0730a519a | ||
![]() |
e60e82c424 | ||
![]() |
7722bb05bc | ||
![]() |
d1e6fce652 | ||
![]() |
eada72e2e1 | ||
![]() |
48617534e9 | ||
![]() |
6717e67352 | ||
![]() |
57e99af9ec | ||
![]() |
db646141c6 | ||
![]() |
f286992b10 | ||
![]() |
7ac38557e6 | ||
![]() |
4833cf4e4a | ||
![]() |
5f95b5caaf | ||
![]() |
540d0e5428 | ||
![]() |
b242b46888 | ||
![]() |
b1fd931cdc | ||
![]() |
6bdb2f3d11 | ||
![]() |
49b375ff94 | ||
![]() |
4d1ef02802 | ||
![]() |
5355fcaba8 | ||
![]() |
d0a59e28ac | ||
![]() |
61a911af41 | ||
![]() |
cc4ebc925c | ||
![]() |
4fa346278c | ||
![]() |
192fe58fc8 | ||
![]() |
dd86de3255 | ||
![]() |
96bcbb43c4 | ||
![]() |
6a8378bec0 | ||
![]() |
f31a580caf | ||
![]() |
016cd8f8ef | ||
![]() |
5802d65ef7 | ||
![]() |
52b80a08c9 | ||
![]() |
3fc2bae49e | ||
![]() |
d1780b8d7e | ||
![]() |
1d9a469f84 | ||
![]() |
6a24667944 | ||
![]() |
227d7c0a99 | ||
![]() |
bd3f075060 | ||
![]() |
9bc68b9a73 | ||
![]() |
0d51d8660e | ||
![]() |
39843319e2 | ||
![]() |
8555e17eb9 | ||
![]() |
844b3f8d23 | ||
![]() |
cf72ade093 | ||
![]() |
bbda1272c2 | ||
![]() |
ea65eb270f | ||
![]() |
52729e9dc8 | ||
![]() |
3d0ea42ac0 | ||
![]() |
c6105580bf | ||
![]() |
ff539f3f05 | ||
![]() |
dba82fedd4 | ||
![]() |
f82f815304 | ||
![]() |
e3335eea00 | ||
![]() |
e8587408ae | ||
![]() |
7f0c97fad8 | ||
![]() |
f1fd8aa51f | ||
![]() |
07de9deab6 | ||
![]() |
65f1e0c71a | ||
![]() |
4c8c8a8c99 | ||
![]() |
9bb7b3b125 | ||
![]() |
4e56339ba1 | ||
![]() |
3d308e0599 | ||
![]() |
d7d7ee6524 | ||
![]() |
abb81704d2 | ||
![]() |
feb36c3efc | ||
![]() |
3761942b82 | ||
![]() |
2ba4c1193c | ||
![]() |
b258e757c2 | ||
![]() |
761067559d | ||
![]() |
96d48c309f | ||
![]() |
597d1e2799 | ||
![]() |
ef039d6a65 | ||
![]() |
f526deaa87 | ||
![]() |
a7e19c8896 | ||
![]() |
ca3842b150 | ||
![]() |
ac1f431f91 | ||
![]() |
20710d8605 | ||
![]() |
53b729a0d1 | ||
![]() |
a6f869aeee | ||
![]() |
ef8e74786f | ||
![]() |
c0be9aca48 | ||
![]() |
cb51a00c37 | ||
![]() |
6f5884805e | ||
![]() |
65450d8518 | ||
![]() |
f1e3023d44 | ||
![]() |
aa4e879e1a | ||
![]() |
43961dc36b | ||
![]() |
24c3cbfff9 | ||
![]() |
95ffe12264 | ||
![]() |
eac5619001 | ||
![]() |
ab9df350fd | ||
![]() |
a58a67923b | ||
![]() |
a92bc562d3 | ||
![]() |
d659502e35 | ||
![]() |
f0487b783d | ||
![]() |
6856735a1d | ||
![]() |
5de21375c0 | ||
![]() |
34e2a1825b | ||
![]() |
e304792f3a | ||
![]() |
02d572aae5 | ||
![]() |
74c23c3e96 | ||
![]() |
1cb161017e | ||
![]() |
9169d73c71 | ||
![]() |
21e551b61d | ||
![]() |
0427d87ba4 | ||
![]() |
da89fa7884 | ||
![]() |
e258ab7ff0 | ||
![]() |
d49c55a8da | ||
![]() |
937b951727 | ||
![]() |
f8570438e9 | ||
![]() |
c3e77487da | ||
![]() |
94b6d09b51 | ||
![]() |
0d5e279509 | ||
![]() |
50cd6be18d | ||
![]() |
4cceb4ad0a | ||
![]() |
353817337e | ||
![]() |
3e9f2b8246 | ||
![]() |
2d70df9776 | ||
![]() |
94fd6cceef | ||
![]() |
214bc81d02 | ||
![]() |
fa956e3153 | ||
![]() |
b626368b6a | ||
![]() |
30e1ff83b9 | ||
![]() |
6e31a2e67d | ||
![]() |
64749a0f85 | ||
![]() |
6baded622b | ||
![]() |
790a136c0a | ||
![]() |
4fc56cec1c | ||
![]() |
93cdd4dbf3 | ||
![]() |
f0f112ff42 | ||
![]() |
93e1f6176a | ||
![]() |
6930aebea2 | ||
![]() |
3546a82cfb | ||
![]() |
7e34c2582f | ||
![]() |
fa41a7c6e7 | ||
![]() |
72a6251042 | ||
![]() |
881b6a831d | ||
![]() |
6d0d5548e5 | ||
![]() |
5cc7605d20 | ||
![]() |
297dd9bbc2 | ||
![]() |
937d993a67 | ||
![]() |
8fe11fec04 | ||
![]() |
ae40f87a5c | ||
![]() |
fd52ff531d | ||
![]() |
0cdd47b014 | ||
![]() |
988d3e9373 | ||
![]() |
39e6bca682 | ||
![]() |
ec14bf215a | ||
![]() |
9713b5806f | ||
![]() |
e287c9cf08 | ||
![]() |
a25f1cc6c3 | ||
![]() |
5bdeb46c12 | ||
![]() |
187f47233c | ||
![]() |
e43fb649a4 | ||
![]() |
aaad986002 | ||
![]() |
95835326f3 | ||
![]() |
e3e9ad1342 | ||
![]() |
20e85e1191 | ||
![]() |
21f4d694bb | ||
![]() |
4ed1f8023b | ||
![]() |
896bdbff8f | ||
![]() |
9d9426f24c | ||
![]() |
970c0e7594 | ||
![]() |
e32a57ce48 | ||
![]() |
f037feaebc | ||
![]() |
485752a033 | ||
![]() |
6c5bcbfc3e | ||
![]() |
7590af3930 | ||
![]() |
d66ddeb69e | ||
![]() |
d0d0403664 | ||
![]() |
1ebc420c75 | ||
![]() |
c291d4aa7d | ||
![]() |
caca762088 | ||
![]() |
b50f3103fe | ||
![]() |
8258dcf41d | ||
![]() |
56f8ced267 | ||
![]() |
d47900473e | ||
![]() |
a91f5b7192 | ||
![]() |
3fdec7946c | ||
![]() |
3fc5f9deb8 | ||
![]() |
c0c30bb1cc | ||
![]() |
74ba209f06 | ||
![]() |
e422274085 | ||
![]() |
5b234b80e8 | ||
![]() |
7b728b17f7 | ||
![]() |
dddcb8e299 | ||
![]() |
c33f309d5f | ||
![]() |
e76db60367 | ||
![]() |
d89bfe79f9 | ||
![]() |
17c9e31e2c | ||
![]() |
2d7b9326ee | ||
![]() |
e53d770b3d | ||
![]() |
1e32d0e2b9 | ||
![]() |
ab512a1273 | ||
![]() |
bbf31b1101 | ||
![]() |
96c6e4c2f4 | ||
![]() |
e208d8b93e | ||
![]() |
31dbdff3c4 | ||
![]() |
0780650015 | ||
![]() |
86fc977ff5 | ||
![]() |
df8e179207 | ||
![]() |
c2f5831181 | ||
![]() |
fe07d79744 | ||
![]() |
0c030cb8cf | ||
![]() |
45e451271e | ||
![]() |
988cbf12ce | ||
![]() |
62c664fbbd | ||
![]() |
63403f894d | ||
![]() |
d498246fb6 | ||
![]() |
6fd39f57ee | ||
![]() |
53e162c922 | ||
![]() |
0b0e323632 | ||
![]() |
809c2980df | ||
![]() |
86e38a8467 | ||
![]() |
a187183bd1 | ||
![]() |
85497c6b75 | ||
![]() |
b3fd8a8343 | ||
![]() |
2f1d989df2 | ||
![]() |
8f2abc2ee1 | ||
![]() |
e940811a8b | ||
![]() |
67312e2d42 | ||
![]() |
364aaceb1c | ||
![]() |
064cc52ad6 | ||
![]() |
76b46b9175 | ||
![]() |
542c6cce25 | ||
![]() |
ce71775722 | ||
![]() |
1e685a4a00 | ||
![]() |
428c376fe4 | ||
![]() |
c403c77cff | ||
![]() |
03a0114e10 | ||
![]() |
34b911203c | ||
![]() |
e8b6ed5a27 | ||
![]() |
c913d17913 | ||
![]() |
a57dca1e11 | ||
![]() |
2c887dfe12 | ||
![]() |
071b8ed8a5 | ||
![]() |
72b0f95719 | ||
![]() |
9e12e3f96c | ||
![]() |
1c7cc63f4c | ||
![]() |
f09a9abc1c | ||
![]() |
6b85e23408 | ||
![]() |
607ba08e23 | ||
![]() |
af97141f4f | ||
![]() |
11994d207a | ||
![]() |
c3a820c4a3 | ||
![]() |
c3aa9f9a6f | ||
![]() |
c4fcd8bd2e | ||
![]() |
fe69a85386 | ||
![]() |
ff1709979f | ||
![]() |
416ee7f143 | ||
![]() |
b209c1a7b5 | ||
![]() |
82b3fe1ab6 | ||
![]() |
7a8d9b6065 | ||
![]() |
f4afa2dc68 | ||
![]() |
2a3947f7cc | ||
![]() |
47a729495d | ||
![]() |
293655f988 | ||
![]() |
0ecaab1a7d | ||
![]() |
9819d70941 | ||
![]() |
abad6dfdd7 | ||
![]() |
dd4e0511a3 | ||
![]() |
d65545964b | ||
![]() |
d1fbcba7b6 | ||
![]() |
1b73bcbff7 | ||
![]() |
7a2f6a5006 | ||
![]() |
2e340d2c2f | ||
![]() |
04e5fc7ccd | ||
![]() |
a9c34b1d2b | ||
![]() |
1c9a36b731 | ||
![]() |
f4c0dc99c2 | ||
![]() |
476235a259 | ||
![]() |
9d0f58009e | ||
![]() |
bb69aba051 | ||
![]() |
49cbc9735c | ||
![]() |
c795c68bc0 | ||
![]() |
d02c432e4d | ||
![]() |
89cbcdb9dc | ||
![]() |
0136c565eb | ||
![]() |
79055487ed | ||
![]() |
57883ec10a | ||
![]() |
4bd9509fa7 | ||
![]() |
695585b68c | ||
![]() |
06ddb2c95e | ||
![]() |
0493f1c206 | ||
![]() |
ecf22198c5 | ||
![]() |
ad0560ef37 | ||
![]() |
c2a21fa496 | ||
![]() |
76e8870e98 | ||
![]() |
a00aa6740e | ||
![]() |
00a4bcff3d | ||
![]() |
8ab1b41974 | ||
![]() |
fa9866db96 | ||
![]() |
99b624a676 | ||
![]() |
e3dc8a1ff2 | ||
![]() |
1b593e3169 | ||
![]() |
13e8e28778 | ||
![]() |
c5ca484eaa | ||
![]() |
ed104d1927 | ||
![]() |
1d987b4846 | ||
![]() |
497c1587fe | ||
![]() |
e86fd9af8a | ||
![]() |
b916eb6cf2 | ||
![]() |
1d01a5ed7b | ||
![]() |
cb40ee342e | ||
![]() |
98ce4897ab | ||
![]() |
167b10ccc1 | ||
![]() |
417e00ee9c | ||
![]() |
00e50d18b9 | ||
![]() |
b7976d2856 | ||
![]() |
ff3d76b464 | ||
![]() |
d2022aa07b | ||
![]() |
d24b02646e | ||
![]() |
60cab62da5 | ||
![]() |
612e27b5ff | ||
![]() |
d9953a8c2f | ||
![]() |
e984e0d414 | ||
![]() |
f8fbe8dba3 | ||
![]() |
b8d6b20c96 | ||
![]() |
c4038c8652 | ||
![]() |
b5a64b3752 | ||
![]() |
bd1336cbdf | ||
![]() |
8768fe1652 | ||
![]() |
37e029b2c1 | ||
![]() |
c55c415933 | ||
![]() |
293db61b32 | ||
![]() |
bdab437574 | ||
![]() |
e89c475856 | ||
![]() |
ee0c32cbb7 | ||
![]() |
2e89ec24f7 | ||
![]() |
b82e64d9cb | ||
![]() |
61fa572068 | ||
![]() |
7f2a2ed23b | ||
![]() |
03582402fa | ||
![]() |
2c6686c5e1 | ||
![]() |
e8c9734f3a | ||
![]() |
a92a7ec848 | ||
![]() |
0a7dc40712 | ||
![]() |
508fc3fa0e | ||
![]() |
ae8a38757a | ||
![]() |
77b6f8c9f2 | ||
![]() |
f06ae1fa95 | ||
![]() |
5fef9653a8 | ||
![]() |
c29f412a70 | ||
![]() |
213496095f | ||
![]() |
020dd39c08 | ||
![]() |
02e2c40c48 | ||
![]() |
e6e3517a94 | ||
![]() |
0bcee21333 | ||
![]() |
a1e2bce1b9 | ||
![]() |
c93fc8af4a | ||
![]() |
c3966a5ef2 | ||
![]() |
1158925b53 | ||
![]() |
bea1570354 | ||
![]() |
561e4b537a | ||
![]() |
ddf7ceecd4 | ||
![]() |
f38e1ae2c0 | ||
![]() |
26bb604243 | ||
![]() |
818949abd9 | ||
![]() |
1a760c63d0 | ||
![]() |
569caf9e40 | ||
![]() |
b226a7183f | ||
![]() |
8b06d1d4bd | ||
![]() |
da30ed06d8 | ||
![]() |
8fec0da5be | ||
![]() |
56186a3d75 | ||
![]() |
2b0914994d | ||
![]() |
8abdc2c969 | ||
![]() |
4d73f107c4 | ||
![]() |
455ac1cadf | ||
![]() |
36cb818cd0 | ||
![]() |
093bd863ba | ||
![]() |
2d6eb5c05d | ||
![]() |
34ac4e78af | ||
![]() |
f6b0f8d6de | ||
![]() |
a39aec862e | ||
![]() |
34d01d5e47 | ||
![]() |
d1464211a6 | ||
![]() |
dcba45e67d | ||
![]() |
fd11748a1a | ||
![]() |
85c856cfa3 | ||
![]() |
da380d89c2 | ||
![]() |
1776540757 | ||
![]() |
3206f4dc83 | ||
![]() |
bbc8748e3b | ||
![]() |
662d79eb86 | ||
![]() |
a07f4e0986 | ||
![]() |
973688d87e | ||
![]() |
7599997a46 | ||
![]() |
b868f13591 | ||
![]() |
a1ebb52813 | ||
![]() |
b55d1127de | ||
![]() |
581c4a4edd | ||
![]() |
9fe142a114 | ||
![]() |
8943954b18 | ||
![]() |
79b1c3f573 | ||
![]() |
69203b5373 | ||
![]() |
46dd245560 | ||
![]() |
bbf36d1a36 | ||
![]() |
ad74d42b15 | ||
![]() |
953963c95b | ||
![]() |
650f2babf9 | ||
![]() |
979dafd0a7 | ||
![]() |
24b8545ebe | ||
![]() |
bf8bfa6321 | ||
![]() |
7fe5fee124 | ||
![]() |
3e7ada2056 | ||
![]() |
7ad75493ff | ||
![]() |
71048545fa | ||
![]() |
49f59007df | ||
![]() |
80b0c10a38 | ||
![]() |
21db4a4160 | ||
![]() |
81b95f4050 | ||
![]() |
632a36d819 | ||
![]() |
84df0efb5e | ||
![]() |
3149cf6849 | ||
![]() |
027ece52e6 | ||
![]() |
19e06c613b | ||
![]() |
5f6bd22f18 | ||
![]() |
3ff5c17009 | ||
![]() |
5d28e109e8 | ||
![]() |
686e6b8fc3 | ||
![]() |
c76b11f9d7 | ||
![]() |
0b9663a23b | ||
![]() |
2f87da8aa9 | ||
![]() |
a7459b3126 | ||
![]() |
a5b7a2c228 | ||
![]() |
2dfd767b8c | ||
![]() |
124ea04e57 | ||
![]() |
0e0f61764a | ||
![]() |
eb1970c015 | ||
![]() |
8cfffd00d6 | ||
![]() |
6652af5cc0 | ||
![]() |
98a8ce0555 | ||
![]() |
3365677484 | ||
![]() |
4001eabafa | ||
![]() |
fdc5208d18 | ||
![]() |
5583f43030 | ||
![]() |
f742875e0d | ||
![]() |
6e2025a748 | ||
![]() |
d7811a4adf | ||
![]() |
2b3f22c871 | ||
![]() |
a756d1e637 | ||
![]() |
3480fb6996 | ||
![]() |
15fe727f2c | ||
![]() |
ae5c50c1b6 | ||
![]() |
2f4c1e683a | ||
![]() |
83a27f4855 | ||
![]() |
b15dad8c4b | ||
![]() |
e0ceacdf85 | ||
![]() |
d7fdbbc2a5 | ||
![]() |
393dd4fe7f | ||
![]() |
bb8e4db47b | ||
![]() |
65d1dfba62 | ||
![]() |
c9380d4972 | ||
![]() |
aa1c5fc43d | ||
![]() |
3e2555e2c1 | ||
![]() |
c505bf2df2 | ||
![]() |
dfd956b083 | ||
![]() |
a50cf1d00a | ||
![]() |
6617d676e5 | ||
![]() |
9f12226b2b | ||
![]() |
d8d48b0a21 | ||
![]() |
0cd8dce9df | ||
![]() |
34751fcd86 | ||
![]() |
b003d9675c | ||
![]() |
98dd56eed5 | ||
![]() |
66e490e55f | ||
![]() |
bbff9ff6a0 | ||
![]() |
0ffeb4dea4 | ||
![]() |
726d5fdd94 | ||
![]() |
4a5a09a0e9 | ||
![]() |
6e87c2ad3e | ||
![]() |
5cf7b1b1bc | ||
![]() |
e766a119d2 | ||
![]() |
7a3c6d6525 | ||
![]() |
945acb4e29 | ||
![]() |
ad5d7ee615 | ||
![]() |
ec17ed9364 | ||
![]() |
4015991622 | ||
![]() |
fa0e12ffe8 | ||
![]() |
908b72370b | ||
![]() |
01d2d2f315 | ||
![]() |
1fc37fec7b | ||
![]() |
d9dba9142c | ||
![]() |
60009ec2f9 | ||
![]() |
7bc8caca96 | ||
![]() |
83d4e5bbb7 | ||
![]() |
59063a7d61 | ||
![]() |
19870ea867 | ||
![]() |
dd459a7855 | ||
![]() |
d5a03b4d6a | ||
![]() |
2a975db9cf | ||
![]() |
bedb0753f3 | ||
![]() |
d0d4e08a2a | ||
![]() |
65eedcf434 | ||
![]() |
36ee9ff58f | ||
![]() |
6ea5c8aed9 | ||
![]() |
92d72f26c7 | ||
![]() |
890562e3ae | ||
![]() |
41421b56a4 | ||
![]() |
2c3618e2c7 | ||
![]() |
967a168ab7 | ||
![]() |
0b32caa71f | ||
![]() |
9b46796969 | ||
![]() |
8409385fca | ||
![]() |
9092b83869 | ||
![]() |
bfba44f6bb | ||
![]() |
432cbd3148 | ||
![]() |
c994904e75 | ||
![]() |
619707e0e3 | ||
![]() |
650d61e4f3 | ||
![]() |
27859a2784 | ||
![]() |
28f78c0c67 | ||
![]() |
a3429848a2 | ||
![]() |
757d05a74e | ||
![]() |
253950f84f | ||
![]() |
af36a67b89 | ||
![]() |
b784cc011d | ||
![]() |
7c0a933452 | ||
![]() |
8b207df819 | ||
![]() |
e6ff8d6839 | ||
![]() |
6fa04aa3e3 | ||
![]() |
2354d0117b | ||
![]() |
f173805c2f | ||
![]() |
b030ed1adf | ||
![]() |
ad22619efb | ||
![]() |
394194d1e6 | ||
![]() |
1acdb28cdd | ||
![]() |
910b6c9c2c | ||
![]() |
9ae08585dc | ||
![]() |
a7dfa60208 | ||
![]() |
1582e4347d | ||
![]() |
72309a0dfc | ||
![]() |
d0040e60cc | ||
![]() |
cecdce07cc | ||
![]() |
cee136ec55 | ||
![]() |
7c9ef39ef6 | ||
![]() |
2e4b4dc188 | ||
![]() |
6ad794e1f8 | ||
![]() |
1dd5a36f5c | ||
![]() |
1e8676bf2c | ||
![]() |
8beaccf2dd | ||
![]() |
24ed932b01 | ||
![]() |
0297c9e612 | ||
![]() |
7c9be024bb | ||
![]() |
f5b628c04f | ||
![]() |
fa4e9c0485 | ||
![]() |
aaf084d713 | ||
![]() |
a6129467aa | ||
![]() |
93919dea88 | ||
![]() |
d297be2698 | ||
![]() |
de67135e86 | ||
![]() |
b684007fbb | ||
![]() |
98347345d1 | ||
![]() |
c0302e6eca | ||
![]() |
06bc98a3a2 | ||
![]() |
32858bcea3 | ||
![]() |
979260f4be | ||
![]() |
408b52de1b | ||
![]() |
b6befa2e83 | ||
![]() |
2d93f8eae8 | ||
![]() |
baa7bb69b3 | ||
![]() |
33dc015083 | ||
![]() |
716cee6907 | ||
![]() |
a224b944e9 | ||
![]() |
37a70c73a5 | ||
![]() |
93c6a9cd96 | ||
![]() |
16e5d02794 | ||
![]() |
4ef581622d | ||
![]() |
0bfcd8c2ab | ||
![]() |
9db6318122 | ||
![]() |
261f0b971c | ||
![]() |
b81b57cdf7 | ||
![]() |
f4c3f5d074 | ||
![]() |
abe3e3094e | ||
![]() |
53d6f4948e | ||
![]() |
1b09c65e74 | ||
![]() |
21649244e9 | ||
![]() |
741c702ff3 | ||
![]() |
cf498b7beb | ||
![]() |
f24fe9c246 | ||
![]() |
d37a5cdde5 | ||
![]() |
a3174a88f5 | ||
![]() |
c3724186cf | ||
![]() |
633f9b2f01 | ||
![]() |
1d7f3416d3 | ||
![]() |
44fefb3216 | ||
![]() |
e938dcfbda | ||
![]() |
20d5d3c162 | ||
![]() |
b12566e265 | ||
![]() |
b430496b13 | ||
![]() |
aed98a830f | ||
![]() |
e65235b207 | ||
![]() |
bf72e3c965 | ||
![]() |
b07d09f7dc | ||
![]() |
41cd90648e | ||
![]() |
e852a2eb9b | ||
![]() |
c62345b9a3 | ||
![]() |
69d1faea35 | ||
![]() |
706eb8f36a | ||
![]() |
ddfbeffd28 | ||
![]() |
d8c2732bcb | ||
![]() |
5b3d094a1e | ||
![]() |
d119c96aee | ||
![]() |
d4111617ca | ||
![]() |
f8d547f2d3 | ||
![]() |
36dde3ff68 | ||
![]() |
209f9b6722 | ||
![]() |
f5cbae0cd5 | ||
![]() |
9ecaa10e51 | ||
![]() |
5cd6370822 | ||
![]() |
ea17d36cbb | ||
![]() |
c3f63e0739 | ||
![]() |
7d77fa92c2 | ||
![]() |
ac0dbb17af | ||
![]() |
7e280e2b27 | ||
![]() |
515ad6164d | ||
![]() |
f0916aeb86 | ||
![]() |
22f17a1887 | ||
![]() |
81914258e9 | ||
![]() |
ec1df9b427 | ||
![]() |
fb484e87c0 | ||
![]() |
5d1d113a25 | ||
![]() |
738d3a13e1 | ||
![]() |
2c58d860b6 | ||
![]() |
d0e26c3dee | ||
![]() |
6eca0b2a39 | ||
![]() |
502f0cd2ce | ||
![]() |
114fbb1278 | ||
![]() |
5d26f5d01d | ||
![]() |
0d58048cea | ||
![]() |
39d5fb82e5 | ||
![]() |
bfbb2826bc | ||
![]() |
aabf0dab88 | ||
![]() |
33eaf081cd | ||
![]() |
95e72b4c4b | ||
![]() |
9e8e5c37f4 | ||
![]() |
1a64108eea | ||
![]() |
ed3f25489e | ||
![]() |
4aaf7c5432 | ||
![]() |
cd3e045e06 | ||
![]() |
b152d59afe | ||
![]() |
9ac1475251 | ||
![]() |
8ed1a29c82 | ||
![]() |
ccbc3b5e39 | ||
![]() |
dbcd5f4c2c | ||
![]() |
34c2579507 | ||
![]() |
eb6fda8387 | ||
![]() |
d8ec1d36b2 | ||
![]() |
aaa073183c | ||
![]() |
8e71559068 | ||
![]() |
87f6b7cdd4 | ||
![]() |
d3b47b6d89 | ||
![]() |
f32f73a7d1 | ||
![]() |
b63f882c3f | ||
![]() |
548e956670 | ||
![]() |
5c28919fba | ||
![]() |
6fe54e31cc | ||
![]() |
e9440c49d5 | ||
![]() |
53844488d8 | ||
![]() |
16a947aa5f | ||
![]() |
c6ab2c5d0a | ||
![]() |
6826a8829c | ||
![]() |
f16090caf4 | ||
![]() |
401dd4a32a | ||
![]() |
b7318b1914 | ||
![]() |
f9ce3f3bc4 | ||
![]() |
e5a081c7dd | ||
![]() |
690579749e | ||
![]() |
4d0c4ac5b3 | ||
![]() |
0bcc8624b7 | ||
![]() |
0bf772b68b | ||
![]() |
8a2b34cc09 | ||
![]() |
1e9bc278e0 | ||
![]() |
0fbdb47dcf | ||
![]() |
366354c90c | ||
![]() |
2e72216a1c | ||
![]() |
63e55bff52 | ||
![]() |
8a8289b1a4 | ||
![]() |
0db8140c13 | ||
![]() |
52939865fa | ||
![]() |
e61da2fff3 | ||
![]() |
5255bf20d3 | ||
![]() |
91271f388c | ||
![]() |
b187b17a4f | ||
![]() |
383db60dff | ||
![]() |
67b18aef5b | ||
![]() |
405c1cdc86 | ||
![]() |
c260b7fa16 | ||
![]() |
804cae02ee | ||
![]() |
609bd6313a | ||
![]() |
67038c6ba8 | ||
![]() |
b45a952d61 | ||
![]() |
e379bfe383 | ||
![]() |
5f36023b9e | ||
![]() |
82739bac3b | ||
![]() |
69a8ba2af8 | ||
![]() |
ef254a1c3d | ||
![]() |
511da9557b | ||
![]() |
bcd604eec2 | ||
![]() |
08fa701854 | ||
![]() |
748ce05341 | ||
![]() |
a3310330f4 | ||
![]() |
aa39dede59 | ||
![]() |
155a5f7c26 | ||
![]() |
af6a4bb6cf | ||
![]() |
872140123d | ||
![]() |
3c7f729b15 | ||
![]() |
81af0e2ada | ||
![]() |
9be06d8be4 | ||
![]() |
2da64b03f3 | ||
![]() |
3ede54def9 | ||
![]() |
3b56e75e1d | ||
![]() |
8f77cc2f7b | ||
![]() |
cdb283319d | ||
![]() |
a30b5690f8 | ||
![]() |
aac65416ff | ||
![]() |
af87168ca3 | ||
![]() |
251a1d6619 | ||
![]() |
fd65ce08c1 | ||
![]() |
62477a3457 | ||
![]() |
a077c280c8 | ||
![]() |
fb3049d6a2 | ||
![]() |
fb420d5952 | ||
![]() |
c1de781a23 | ||
![]() |
05f93f27df | ||
![]() |
99c815bcbd | ||
![]() |
d60c52bbc7 | ||
![]() |
9964bd40ed | ||
![]() |
317bd8ffd2 | ||
![]() |
572d5a09cd | ||
![]() |
368116d242 | ||
![]() |
550f9ba9b0 | ||
![]() |
b067e1deee | ||
![]() |
aa8f3ad307 | ||
![]() |
03ce1f46f6 | ||
![]() |
4343e84ecf | ||
![]() |
80890f0096 | ||
![]() |
a58e428f48 | ||
![]() |
adc88deaa8 | ||
![]() |
ad025f0b3b | ||
![]() |
90c308a393 | ||
![]() |
6fd756299e | ||
![]() |
00182e7b9f | ||
![]() |
3871688dfb | ||
![]() |
4c2b12d8f1 | ||
![]() |
af7bf428d8 | ||
![]() |
cbccf011e7 | ||
![]() |
2b37cbe079 | ||
![]() |
d0983b69df | ||
![]() |
d0632ab636 | ||
![]() |
aeb0504c1c | ||
![]() |
621c375a25 | ||
![]() |
1499c0a563 | ||
![]() |
09ee52c4cb | ||
![]() |
663acfe89f | ||
![]() |
07d7191db3 | ||
![]() |
c89c0d7824 | ||
![]() |
0f5d300db4 | ||
![]() |
270e87166c | ||
![]() |
50bb249a93 | ||
![]() |
3f1d25b9d0 | ||
![]() |
6b97b4f5ac | ||
![]() |
76be95d7e0 | ||
![]() |
ae7d464878 | ||
![]() |
a58e357cd5 | ||
![]() |
43c7a8a119 | ||
![]() |
7128092139 | ||
![]() |
16ccf0affd | ||
![]() |
e5872cc0e4 | ||
![]() |
27ef8a1ced | ||
![]() |
bea3d841d2 | ||
![]() |
0426b70046 | ||
![]() |
c47fd90eb3 | ||
![]() |
a773534809 | ||
![]() |
d0668d3a6c | ||
![]() |
f49ce5d1b4 | ||
![]() |
e5a2b0d2d8 | ||
![]() |
7ba9bcebed | ||
![]() |
3bd5d83c9c | ||
![]() |
0f3b7b73af | ||
![]() |
38d2410156 | ||
![]() |
82693d9dca | ||
![]() |
a88ac1e1fc | ||
![]() |
37bef01f67 | ||
![]() |
7c3e64673f | ||
![]() |
16b59220f3 | ||
![]() |
050a558243 | ||
![]() |
ddb049e884 | ||
![]() |
891640972b | ||
![]() |
2e824f3fa5 | ||
![]() |
4ca643342e | ||
![]() |
f8651d9faa | ||
![]() |
b826970b16 | ||
![]() |
ba356c41e0 | ||
![]() |
b9f97e64f8 | ||
![]() |
89599bc3cf | ||
![]() |
c989f6dc09 | ||
![]() |
706bc4c307 | ||
![]() |
c9a97da0ef | ||
![]() |
b3d46aa074 | ||
![]() |
4a28133f11 | ||
![]() |
308421f1d6 | ||
![]() |
03bfff3660 | ||
![]() |
0fb73a6332 | ||
![]() |
711b8e10a3 | ||
![]() |
9b77e16ffc | ||
![]() |
6749424508 | ||
![]() |
f6f84fc201 | ||
![]() |
34ccb6588c | ||
![]() |
2088092f7c | ||
![]() |
0067b6a84d | ||
![]() |
80c108c25a | ||
![]() |
53545c984b | ||
![]() |
01fd33f173 | ||
![]() |
3ad59f877c | ||
![]() |
c1aaceebb6 | ||
![]() |
404b1f40d6 | ||
![]() |
3062312649 | ||
![]() |
10893f6246 | ||
![]() |
e3aa4679a0 | ||
![]() |
d79067db7e | ||
![]() |
f0dda4f875 | ||
![]() |
b56f4bd9f8 | ||
![]() |
992793295c | ||
![]() |
debb928b30 | ||
![]() |
6ca476fe21 | ||
![]() |
b64ae55c66 | ||
![]() |
8bc775dacc | ||
![]() |
988a335e9d | ||
![]() |
f7c4900d5c | ||
![]() |
c3b5bf7437 | ||
![]() |
a08cb2ca9d | ||
![]() |
a882cfafb1 | ||
![]() |
3d08601796 | ||
![]() |
63af60c7e7 | ||
![]() |
93df0a6d70 | ||
![]() |
ff3407ea25 | ||
![]() |
79fb722657 | ||
![]() |
3eb6e75d3e | ||
![]() |
6d6188e34d | ||
![]() |
fa6bd786d2 | ||
![]() |
c6ed7754c7 | ||
![]() |
b4aa6f9f8b | ||
![]() |
c71fcc8cbb | ||
![]() |
83b41897f8 | ||
![]() |
c630037f04 | ||
![]() |
5ba38e5053 | ||
![]() |
95d980da4a | ||
![]() |
7b855927e2 | ||
![]() |
b63655057c | ||
![]() |
4b3ad0a1cd | ||
![]() |
9ade1de3d5 | ||
![]() |
333c151955 | ||
![]() |
ebcee2eb35 | ||
![]() |
15b28bda14 | ||
![]() |
c03832da63 | ||
![]() |
ffcdd85117 | ||
![]() |
0b11fda017 | ||
![]() |
3832c8efd9 | ||
![]() |
6fd8a7a34e | ||
![]() |
4b2ebf5487 | ||
![]() |
045cdee30c | ||
![]() |
146b5691e7 | ||
![]() |
fe5f8e041b | ||
![]() |
13f634fa16 | ||
![]() |
7c0d5526f3 | ||
![]() |
780376e411 | ||
![]() |
1879183b24 | ||
![]() |
ccb77ba1e9 | ||
![]() |
7da3065de6 | ||
![]() |
813e60d31a | ||
![]() |
1b70ea0c3f | ||
![]() |
d57dbb4319 | ||
![]() |
80aebcc7d2 | ||
![]() |
76b956a969 | ||
![]() |
1aafa459e5 | ||
![]() |
e33a3bb94a | ||
![]() |
07f3d6ebd8 | ||
![]() |
c460b7abc9 | ||
![]() |
5805fbb99f | ||
![]() |
a445ebdf3c | ||
![]() |
78e53e35c2 | ||
![]() |
0c771f1c42 | ||
![]() |
eb66da6436 | ||
![]() |
3eb6a68d12 | ||
![]() |
cd5f6a0c56 | ||
![]() |
ab6d6ac1ce | ||
![]() |
573134fcb4 | ||
![]() |
5ecb3f9be2 | ||
![]() |
ab4687d914 | ||
![]() |
b859be8cea | ||
![]() |
187a20288b | ||
![]() |
7e664fbb3b | ||
![]() |
91799e2b52 | ||
![]() |
98bcf4f28d | ||
![]() |
a6fb9e6100 | ||
![]() |
f352c51990 | ||
![]() |
094f7ee718 | ||
![]() |
a7cf76491b | ||
![]() |
58a9142f42 | ||
![]() |
f6df85f8ce | ||
![]() |
4679e670f1 | ||
![]() |
f3039f96ec | ||
![]() |
4ec71c58bd | ||
![]() |
8bce9be590 | ||
![]() |
49bbdb3c21 | ||
![]() |
e60b975b10 | ||
![]() |
a87c29b5d9 | ||
![]() |
0a982f6fab | ||
![]() |
0f8b934e68 | ||
![]() |
235298a1b2 | ||
![]() |
cf3f755edc | ||
![]() |
0cc1a17d04 | ||
![]() |
f5fa7e4400 | ||
![]() |
d08d00daa7 | ||
![]() |
a015e551eb | ||
![]() |
bcabf6da91 | ||
![]() |
3498882fe1 | ||
![]() |
52f3238e17 | ||
![]() |
0a0b60566d | ||
![]() |
247bc6f673 | ||
![]() |
b9d957837e | ||
![]() |
f8d11c843d | ||
![]() |
431045f036 | ||
![]() |
10786bbe7f | ||
![]() |
352c572e5d | ||
![]() |
0edd7302d5 | ||
![]() |
06e977b444 | ||
![]() |
01ba578016 | ||
![]() |
c1ec8971ae | ||
![]() |
7746ecc9fb | ||
![]() |
24289d5dbb | ||
![]() |
38210ebbc6 | ||
![]() |
b78f163bb0 | ||
![]() |
86c27b50f1 | ||
![]() |
333dccc7af | ||
![]() |
61475d0a0c | ||
![]() |
4d17b18761 | ||
![]() |
2f46a81e3e | ||
![]() |
fae47358b8 | ||
![]() |
0f43476d03 | ||
![]() |
856f8fd6de | ||
![]() |
bba47ad9b1 | ||
![]() |
79f131066c | ||
![]() |
ac237ee10f | ||
![]() |
11debb1568 | ||
![]() |
b0942d86fe | ||
![]() |
12510b0c97 | ||
![]() |
cc7bed5dab | ||
![]() |
b0e2f5f375 | ||
![]() |
89a9634d35 | ||
![]() |
0f72008090 | ||
![]() |
7ef33a7219 | ||
![]() |
b96ce9c210 | ||
![]() |
7b4df98875 | ||
![]() |
5badbcb012 | ||
![]() |
ca265966e7 | ||
![]() |
af5374d38b | ||
![]() |
76fa581bb9 | ||
![]() |
4a374f0378 | ||
![]() |
15165a3c93 | ||
![]() |
584ce043e5 | ||
![]() |
b0df223f5a | ||
![]() |
201dab93ff | ||
![]() |
10f296ba17 | ||
![]() |
464f17f182 | ||
![]() |
a63a11a11a | ||
![]() |
c1194c90cb | ||
![]() |
4acc6f333e | ||
![]() |
07aba74757 | ||
![]() |
4fd27e879e | ||
![]() |
ec13eecc59 | ||
![]() |
e48bcd2070 | ||
![]() |
d454f85572 | ||
![]() |
4e10ca3214 | ||
![]() |
50dd6b69cd | ||
![]() |
8a9b19f327 | ||
![]() |
680f8f8d5a | ||
![]() |
fe5bf96e5d | ||
![]() |
7d74b74570 | ||
![]() |
a4501b93c4 | ||
![]() |
39a5f68914 | ||
![]() |
3a2d4ac7fa | ||
![]() |
76db2b39b0 | ||
![]() |
fe1a7f6d69 | ||
![]() |
0eaa6045c1 | ||
![]() |
40573bf393 | ||
![]() |
56907392d3 | ||
![]() |
30df871787 | ||
![]() |
fd1a8dd96c | ||
![]() |
f42eb0d5ca | ||
![]() |
98a388e65a | ||
![]() |
6d9fa34f65 | ||
![]() |
2dd0a182ab | ||
![]() |
15773cb3e0 | ||
![]() |
4aedafc73a | ||
![]() |
25b093e69e | ||
![]() |
140fc48ede | ||
![]() |
fea5d007fc | ||
![]() |
c423501804 | ||
![]() |
9137957cf9 | ||
![]() |
f4528d0db2 | ||
![]() |
5bc6ed4cef | ||
![]() |
7968cd650a | ||
![]() |
cbb76be9d0 | ||
![]() |
9f855c7d01 | ||
![]() |
bd42827d43 | ||
![]() |
47220ae4a6 |
156
.coveragerc
156
.coveragerc
@@ -25,18 +25,19 @@ omit =
|
||||
homeassistant/components/ads/*
|
||||
homeassistant/components/aftership/sensor.py
|
||||
homeassistant/components/agent_dvr/__init__.py
|
||||
homeassistant/components/agent_dvr/alarm_control_panel.py
|
||||
homeassistant/components/agent_dvr/camera.py
|
||||
homeassistant/components/agent_dvr/const.py
|
||||
homeassistant/components/agent_dvr/helpers.py
|
||||
homeassistant/components/airly/__init__.py
|
||||
homeassistant/components/airly/air_quality.py
|
||||
homeassistant/components/airly/sensor.py
|
||||
homeassistant/components/airly/const.py
|
||||
homeassistant/components/airvisual/__init__.py
|
||||
homeassistant/components/airvisual/air_quality.py
|
||||
homeassistant/components/airvisual/sensor.py
|
||||
homeassistant/components/aladdin_connect/cover.py
|
||||
homeassistant/components/alarmdecoder/*
|
||||
homeassistant/components/alarmdecoder/__init__.py
|
||||
homeassistant/components/alarmdecoder/alarm_control_panel.py
|
||||
homeassistant/components/alarmdecoder/binary_sensor.py
|
||||
homeassistant/components/alarmdecoder/const.py
|
||||
homeassistant/components/alarmdecoder/sensor.py
|
||||
homeassistant/components/alpha_vantage/sensor.py
|
||||
homeassistant/components/amazon_polly/tts.py
|
||||
homeassistant/components/ambiclimate/climate.py
|
||||
@@ -69,6 +70,9 @@ omit =
|
||||
homeassistant/components/avion/light.py
|
||||
homeassistant/components/avri/const.py
|
||||
homeassistant/components/avri/sensor.py
|
||||
homeassistant/components/azure_devops/__init__.py
|
||||
homeassistant/components/azure_devops/const.py
|
||||
homeassistant/components/azure_devops/sensor.py
|
||||
homeassistant/components/azure_service_bus/*
|
||||
homeassistant/components/baidu/tts.py
|
||||
homeassistant/components/beewi_smartclim/sensor.py
|
||||
@@ -100,11 +104,11 @@ omit =
|
||||
homeassistant/components/braviatv/__init__.py
|
||||
homeassistant/components/braviatv/const.py
|
||||
homeassistant/components/braviatv/media_player.py
|
||||
homeassistant/components/broadlink/__init__.py
|
||||
homeassistant/components/broadlink/const.py
|
||||
homeassistant/components/broadlink/device.py
|
||||
homeassistant/components/broadlink/remote.py
|
||||
homeassistant/components/broadlink/sensor.py
|
||||
homeassistant/components/broadlink/switch.py
|
||||
homeassistant/components/broadlink/updater.py
|
||||
homeassistant/components/brottsplatskartan/sensor.py
|
||||
homeassistant/components/browser/*
|
||||
homeassistant/components/brunt/cover.py
|
||||
@@ -117,7 +121,6 @@ omit =
|
||||
homeassistant/components/buienradar/util.py
|
||||
homeassistant/components/buienradar/weather.py
|
||||
homeassistant/components/caldav/calendar.py
|
||||
homeassistant/components/canary/alarm_control_panel.py
|
||||
homeassistant/components/canary/camera.py
|
||||
homeassistant/components/cast/*
|
||||
homeassistant/components/cert_expiry/helper.py
|
||||
@@ -139,6 +142,10 @@ omit =
|
||||
homeassistant/components/comfoconnect/*
|
||||
homeassistant/components/concord232/alarm_control_panel.py
|
||||
homeassistant/components/concord232/binary_sensor.py
|
||||
homeassistant/components/control4/__init__.py
|
||||
homeassistant/components/control4/light.py
|
||||
homeassistant/components/control4/const.py
|
||||
homeassistant/components/control4/director_utils.py
|
||||
homeassistant/components/coolmaster/__init__.py
|
||||
homeassistant/components/coolmaster/climate.py
|
||||
homeassistant/components/coolmaster/const.py
|
||||
@@ -162,8 +169,12 @@ omit =
|
||||
homeassistant/components/deutsche_bahn/sensor.py
|
||||
homeassistant/components/devolo_home_control/__init__.py
|
||||
homeassistant/components/devolo_home_control/binary_sensor.py
|
||||
homeassistant/components/devolo_home_control/climate.py
|
||||
homeassistant/components/devolo_home_control/const.py
|
||||
homeassistant/components/devolo_home_control/cover.py
|
||||
homeassistant/components/devolo_home_control/devolo_device.py
|
||||
homeassistant/components/devolo_home_control/devolo_multi_level_switch.py
|
||||
homeassistant/components/devolo_home_control/light.py
|
||||
homeassistant/components/devolo_home_control/sensor.py
|
||||
homeassistant/components/devolo_home_control/subscriber.py
|
||||
homeassistant/components/devolo_home_control/switch.py
|
||||
@@ -212,9 +223,15 @@ omit =
|
||||
homeassistant/components/emby/media_player.py
|
||||
homeassistant/components/emoncms/sensor.py
|
||||
homeassistant/components/emoncms_history/*
|
||||
homeassistant/components/emulated_hue/upnp.py
|
||||
homeassistant/components/enigma2/media_player.py
|
||||
homeassistant/components/enocean/*
|
||||
homeassistant/components/enocean/__init__.py
|
||||
homeassistant/components/enocean/binary_sensor.py
|
||||
homeassistant/components/enocean/const.py
|
||||
homeassistant/components/enocean/device.py
|
||||
homeassistant/components/enocean/dongle.py
|
||||
homeassistant/components/enocean/light.py
|
||||
homeassistant/components/enocean/sensor.py
|
||||
homeassistant/components/enocean/switch.py
|
||||
homeassistant/components/enphase_envoy/sensor.py
|
||||
homeassistant/components/entur_public_transport/*
|
||||
homeassistant/components/environment_canada/*
|
||||
@@ -247,6 +264,15 @@ omit =
|
||||
homeassistant/components/fibaro/*
|
||||
homeassistant/components/filesize/sensor.py
|
||||
homeassistant/components/fints/sensor.py
|
||||
homeassistant/components/firmata/__init__.py
|
||||
homeassistant/components/firmata/binary_sensor.py
|
||||
homeassistant/components/firmata/board.py
|
||||
homeassistant/components/firmata/const.py
|
||||
homeassistant/components/firmata/entity.py
|
||||
homeassistant/components/firmata/light.py
|
||||
homeassistant/components/firmata/pin.py
|
||||
homeassistant/components/firmata/sensor.py
|
||||
homeassistant/components/firmata/switch.py
|
||||
homeassistant/components/fitbit/sensor.py
|
||||
homeassistant/components/fixer/sensor.py
|
||||
homeassistant/components/fleetgo/device_tracker.py
|
||||
@@ -286,8 +312,6 @@ omit =
|
||||
homeassistant/components/gc100/*
|
||||
homeassistant/components/geniushub/*
|
||||
homeassistant/components/geizhals/sensor.py
|
||||
homeassistant/components/gios/__init__.py
|
||||
homeassistant/components/gios/air_quality.py
|
||||
homeassistant/components/github/sensor.py
|
||||
homeassistant/components/gitlab_ci/sensor.py
|
||||
homeassistant/components/gitter/sensor.py
|
||||
@@ -296,6 +320,8 @@ omit =
|
||||
homeassistant/components/glances/sensor.py
|
||||
homeassistant/components/gntp/notify.py
|
||||
homeassistant/components/goalfeed/*
|
||||
homeassistant/components/goalzero/__init__.py
|
||||
homeassistant/components/goalzero/binary_sensor.py
|
||||
homeassistant/components/google/*
|
||||
homeassistant/components/google_cloud/tts.py
|
||||
homeassistant/components/google_maps/device_tracker.py
|
||||
@@ -313,6 +339,7 @@ omit =
|
||||
homeassistant/components/guardian/binary_sensor.py
|
||||
homeassistant/components/guardian/sensor.py
|
||||
homeassistant/components/guardian/switch.py
|
||||
homeassistant/components/guardian/util.py
|
||||
homeassistant/components/habitica/*
|
||||
homeassistant/components/hangouts/*
|
||||
homeassistant/components/hangouts/__init__.py
|
||||
@@ -329,7 +356,8 @@ omit =
|
||||
homeassistant/components/hisense_aehw4a1/*
|
||||
homeassistant/components/hitron_coda/device_tracker.py
|
||||
homeassistant/components/hive/*
|
||||
homeassistant/components/hlk_sw16/*
|
||||
homeassistant/components/hlk_sw16/__init__.py
|
||||
homeassistant/components/hlk_sw16/switch.py
|
||||
homeassistant/components/home_connect/*
|
||||
homeassistant/components/homematic/*
|
||||
homeassistant/components/homematic/climate.py
|
||||
@@ -348,6 +376,7 @@ omit =
|
||||
homeassistant/components/hunterdouglas_powerview/sensor.py
|
||||
homeassistant/components/hunterdouglas_powerview/cover.py
|
||||
homeassistant/components/hunterdouglas_powerview/entity.py
|
||||
homeassistant/components/hvv_departures/binary_sensor.py
|
||||
homeassistant/components/hvv_departures/sensor.py
|
||||
homeassistant/components/hvv_departures/__init__.py
|
||||
homeassistant/components/hydrawise/*
|
||||
@@ -372,8 +401,17 @@ omit =
|
||||
homeassistant/components/ihc/*
|
||||
homeassistant/components/imap/sensor.py
|
||||
homeassistant/components/imap_email_content/sensor.py
|
||||
homeassistant/components/influxdb/sensor.py
|
||||
homeassistant/components/insteon/*
|
||||
homeassistant/components/insteon/binary_sensor.py
|
||||
homeassistant/components/insteon/climate.py
|
||||
homeassistant/components/insteon/const.py
|
||||
homeassistant/components/insteon/cover.py
|
||||
homeassistant/components/insteon/fan.py
|
||||
homeassistant/components/insteon/insteon_entity.py
|
||||
homeassistant/components/insteon/ipdb.py
|
||||
homeassistant/components/insteon/light.py
|
||||
homeassistant/components/insteon/schemas.py
|
||||
homeassistant/components/insteon/switch.py
|
||||
homeassistant/components/insteon/utils.py
|
||||
homeassistant/components/incomfort/*
|
||||
homeassistant/components/intesishome/*
|
||||
homeassistant/components/ios/*
|
||||
@@ -416,6 +454,7 @@ omit =
|
||||
homeassistant/components/knx/climate.py
|
||||
homeassistant/components/knx/cover.py
|
||||
homeassistant/components/kodi/__init__.py
|
||||
homeassistant/components/kodi/browse_media.py
|
||||
homeassistant/components/kodi/const.py
|
||||
homeassistant/components/kodi/media_player.py
|
||||
homeassistant/components/kodi/notify.py
|
||||
@@ -436,8 +475,6 @@ omit =
|
||||
homeassistant/components/lightwave/*
|
||||
homeassistant/components/limitlessled/light.py
|
||||
homeassistant/components/linksys_smart/device_tracker.py
|
||||
homeassistant/components/linky/__init__.py
|
||||
homeassistant/components/linky/sensor.py
|
||||
homeassistant/components/linode/*
|
||||
homeassistant/components/linux_battery/sensor.py
|
||||
homeassistant/components/lirc/*
|
||||
@@ -449,7 +486,8 @@ omit =
|
||||
homeassistant/components/london_underground/sensor.py
|
||||
homeassistant/components/loopenergy/sensor.py
|
||||
homeassistant/components/luci/device_tracker.py
|
||||
homeassistant/components/luftdaten/*
|
||||
homeassistant/components/luftdaten/__init__.py
|
||||
homeassistant/components/luftdaten/sensor.py
|
||||
homeassistant/components/lupusec/*
|
||||
homeassistant/components/lutron/*
|
||||
homeassistant/components/lutron_caseta/__init__.py
|
||||
@@ -501,7 +539,9 @@ omit =
|
||||
homeassistant/components/mjpeg/camera.py
|
||||
homeassistant/components/mobile_app/*
|
||||
homeassistant/components/mochad/*
|
||||
homeassistant/components/modbus/*
|
||||
homeassistant/components/modbus/climate.py
|
||||
homeassistant/components/modbus/cover.py
|
||||
homeassistant/components/modbus/switch.py
|
||||
homeassistant/components/modem_callerid/sensor.py
|
||||
homeassistant/components/mpchc/media_player.py
|
||||
homeassistant/components/mpd/media_player.py
|
||||
@@ -530,7 +570,12 @@ omit =
|
||||
homeassistant/components/netatmo/camera.py
|
||||
homeassistant/components/netatmo/climate.py
|
||||
homeassistant/components/netatmo/const.py
|
||||
homeassistant/components/netatmo/data_handler.py
|
||||
homeassistant/components/netatmo/helper.py
|
||||
homeassistant/components/netatmo/light.py
|
||||
homeassistant/components/netatmo/netatmo_entity_base.py
|
||||
homeassistant/components/netatmo/sensor.py
|
||||
homeassistant/components/netatmo/webhook.py
|
||||
homeassistant/components/netdata/sensor.py
|
||||
homeassistant/components/netgear/device_tracker.py
|
||||
homeassistant/components/netgear_lte/*
|
||||
@@ -554,14 +599,17 @@ omit =
|
||||
homeassistant/components/nuki/lock.py
|
||||
homeassistant/components/nut/sensor.py
|
||||
homeassistant/components/nx584/alarm_control_panel.py
|
||||
homeassistant/components/nzbget/__init__.py
|
||||
homeassistant/components/nzbget/sensor.py
|
||||
homeassistant/components/nzbget/coordinator.py
|
||||
homeassistant/components/obihai/*
|
||||
homeassistant/components/octoprint/*
|
||||
homeassistant/components/oem/climate.py
|
||||
homeassistant/components/oasa_telematics/sensor.py
|
||||
homeassistant/components/ohmconnect/sensor.py
|
||||
homeassistant/components/ombi/*
|
||||
homeassistant/components/omnilogic/__init__.py
|
||||
homeassistant/components/omnilogic/common.py
|
||||
homeassistant/components/omnilogic/sensor.py
|
||||
homeassistant/components/onewire/const.py
|
||||
homeassistant/components/onewire/sensor.py
|
||||
homeassistant/components/onkyo/media_player.py
|
||||
homeassistant/components/onvif/__init__.py
|
||||
@@ -590,6 +638,9 @@ omit =
|
||||
homeassistant/components/openuv/sensor.py
|
||||
homeassistant/components/openweathermap/sensor.py
|
||||
homeassistant/components/openweathermap/weather.py
|
||||
homeassistant/components/openweathermap/forecast_update_coordinator.py
|
||||
homeassistant/components/openweathermap/weather_update_coordinator.py
|
||||
homeassistant/components/openweathermap/abstract_owm_sensor.py
|
||||
homeassistant/components/opnsense/*
|
||||
homeassistant/components/opple/light.py
|
||||
homeassistant/components/orangepi_gpio/*
|
||||
@@ -597,6 +648,9 @@ omit =
|
||||
homeassistant/components/orvibo/switch.py
|
||||
homeassistant/components/osramlightify/light.py
|
||||
homeassistant/components/otp/sensor.py
|
||||
homeassistant/components/ovo_energy/__init__.py
|
||||
homeassistant/components/ovo_energy/const.py
|
||||
homeassistant/components/ovo_energy/sensor.py
|
||||
homeassistant/components/panasonic_bluray/media_player.py
|
||||
homeassistant/components/panasonic_viera/media_player.py
|
||||
homeassistant/components/pandora/media_player.py
|
||||
@@ -609,6 +663,7 @@ omit =
|
||||
homeassistant/components/picotts/tts.py
|
||||
homeassistant/components/piglow/light.py
|
||||
homeassistant/components/pilight/*
|
||||
homeassistant/components/ping/const.py
|
||||
homeassistant/components/ping/binary_sensor.py
|
||||
homeassistant/components/ping/device_tracker.py
|
||||
homeassistant/components/pioneer/media_player.py
|
||||
@@ -616,16 +671,16 @@ omit =
|
||||
homeassistant/components/plaato/*
|
||||
homeassistant/components/plex/media_player.py
|
||||
homeassistant/components/plex/sensor.py
|
||||
homeassistant/components/plugwise/__init__.py
|
||||
homeassistant/components/plugwise/binary_sensor.py
|
||||
homeassistant/components/plugwise/climate.py
|
||||
homeassistant/components/plugwise/sensor.py
|
||||
homeassistant/components/plugwise/switch.py
|
||||
homeassistant/components/plum_lightpad/*
|
||||
homeassistant/components/plum_lightpad/light.py
|
||||
homeassistant/components/pocketcasts/sensor.py
|
||||
homeassistant/components/point/*
|
||||
homeassistant/components/prezzibenzina/sensor.py
|
||||
homeassistant/components/poolsense/__init__.py
|
||||
homeassistant/components/poolsense/sensor.py
|
||||
homeassistant/components/poolsense/binary_sensor.py
|
||||
homeassistant/components/proliphix/climate.py
|
||||
homeassistant/components/progettihwsw/__init__.py
|
||||
homeassistant/components/progettihwsw/binary_sensor.py
|
||||
homeassistant/components/progettihwsw/switch.py
|
||||
homeassistant/components/prometheus/*
|
||||
homeassistant/components/prowl/notify.py
|
||||
homeassistant/components/proxmoxve/*
|
||||
@@ -668,7 +723,6 @@ omit =
|
||||
homeassistant/components/rest/binary_sensor.py
|
||||
homeassistant/components/rest/notify.py
|
||||
homeassistant/components/rest/switch.py
|
||||
homeassistant/components/rfxtrx/*
|
||||
homeassistant/components/ring/camera.py
|
||||
homeassistant/components/ripple/sensor.py
|
||||
homeassistant/components/rocketchat/notify.py
|
||||
@@ -678,6 +732,10 @@ omit =
|
||||
homeassistant/components/roomba/roomba.py
|
||||
homeassistant/components/roomba/sensor.py
|
||||
homeassistant/components/roomba/vacuum.py
|
||||
homeassistant/components/roon/__init__.py
|
||||
homeassistant/components/roon/const.py
|
||||
homeassistant/components/roon/media_player.py
|
||||
homeassistant/components/roon/server.py
|
||||
homeassistant/components/route53/*
|
||||
homeassistant/components/rova/sensor.py
|
||||
homeassistant/components/rpi_camera/*
|
||||
@@ -702,7 +760,6 @@ omit =
|
||||
homeassistant/components/sensehat/light.py
|
||||
homeassistant/components/sensehat/sensor.py
|
||||
homeassistant/components/sensibo/climate.py
|
||||
homeassistant/components/sentry/__init__.py
|
||||
homeassistant/components/serial/sensor.py
|
||||
homeassistant/components/serial_pm/sensor.py
|
||||
homeassistant/components/sesame/lock.py
|
||||
@@ -710,6 +767,13 @@ omit =
|
||||
homeassistant/components/seventeentrack/sensor.py
|
||||
homeassistant/components/shiftr/*
|
||||
homeassistant/components/shodan/sensor.py
|
||||
homeassistant/components/shelly/__init__.py
|
||||
homeassistant/components/shelly/binary_sensor.py
|
||||
homeassistant/components/shelly/cover.py
|
||||
homeassistant/components/shelly/entity.py
|
||||
homeassistant/components/shelly/light.py
|
||||
homeassistant/components/shelly/sensor.py
|
||||
homeassistant/components/shelly/switch.py
|
||||
homeassistant/components/sht31/sensor.py
|
||||
homeassistant/components/sigfox/sensor.py
|
||||
homeassistant/components/simplepush/notify.py
|
||||
@@ -718,7 +782,7 @@ omit =
|
||||
homeassistant/components/simplisafe/lock.py
|
||||
homeassistant/components/simulated/sensor.py
|
||||
homeassistant/components/sisyphus/*
|
||||
homeassistant/components/sky_hub/device_tracker.py
|
||||
homeassistant/components/sky_hub/*
|
||||
homeassistant/components/skybeacon/sensor.py
|
||||
homeassistant/components/skybell/*
|
||||
homeassistant/components/slack/notify.py
|
||||
@@ -731,7 +795,9 @@ omit =
|
||||
homeassistant/components/smappee/sensor.py
|
||||
homeassistant/components/smappee/switch.py
|
||||
homeassistant/components/smarty/*
|
||||
homeassistant/components/smarthab/*
|
||||
homeassistant/components/smarthab/__init__.py
|
||||
homeassistant/components/smarthab/cover.py
|
||||
homeassistant/components/smarthab/light.py
|
||||
homeassistant/components/sms/*
|
||||
homeassistant/components/smtp/notify.py
|
||||
homeassistant/components/snapcast/*
|
||||
@@ -752,6 +818,7 @@ omit =
|
||||
homeassistant/components/spc/*
|
||||
homeassistant/components/speedtestdotnet/*
|
||||
homeassistant/components/spider/*
|
||||
homeassistant/components/splunk/*
|
||||
homeassistant/components/spotcrime/sensor.py
|
||||
homeassistant/components/spotify/__init__.py
|
||||
homeassistant/components/spotify/media_player.py
|
||||
@@ -766,7 +833,8 @@ omit =
|
||||
homeassistant/components/streamlabswater/*
|
||||
homeassistant/components/suez_water/*
|
||||
homeassistant/components/supervisord/sensor.py
|
||||
homeassistant/components/surepetcare/*.py
|
||||
homeassistant/components/surepetcare/__init__.py
|
||||
homeassistant/components/surepetcare/sensor.py
|
||||
homeassistant/components/swiss_hydrological_data/sensor.py
|
||||
homeassistant/components/swiss_public_transport/sensor.py
|
||||
homeassistant/components/swisscom/device_tracker.py
|
||||
@@ -778,7 +846,9 @@ omit =
|
||||
homeassistant/components/synology_chat/notify.py
|
||||
homeassistant/components/synology_dsm/__init__.py
|
||||
homeassistant/components/synology_dsm/binary_sensor.py
|
||||
homeassistant/components/synology_dsm/camera.py
|
||||
homeassistant/components/synology_dsm/sensor.py
|
||||
homeassistant/components/synology_dsm/switch.py
|
||||
homeassistant/components/synology_srm/device_tracker.py
|
||||
homeassistant/components/syslog/notify.py
|
||||
homeassistant/components/systemmonitor/sensor.py
|
||||
@@ -792,7 +862,13 @@ omit =
|
||||
homeassistant/components/ted5000/sensor.py
|
||||
homeassistant/components/telegram/notify.py
|
||||
homeassistant/components/telegram_bot/*
|
||||
homeassistant/components/tellduslive/*
|
||||
homeassistant/components/tellduslive/__init__.py
|
||||
homeassistant/components/tellduslive/binary_sensor.py
|
||||
homeassistant/components/tellduslive/cover.py
|
||||
homeassistant/components/tellduslive/entry.py
|
||||
homeassistant/components/tellduslive/light.py
|
||||
homeassistant/components/tellduslive/sensor.py
|
||||
homeassistant/components/tellduslive/switch.py
|
||||
homeassistant/components/tellstick/*
|
||||
homeassistant/components/telnet/switch.py
|
||||
homeassistant/components/temper/sensor.py
|
||||
@@ -811,7 +887,9 @@ omit =
|
||||
homeassistant/components/thingspeak/*
|
||||
homeassistant/components/thinkingcleaner/*
|
||||
homeassistant/components/thomson/device_tracker.py
|
||||
homeassistant/components/tibber/*
|
||||
homeassistant/components/tibber/__init__.py
|
||||
homeassistant/components/tibber/notify.py
|
||||
homeassistant/components/tibber/sensor.py
|
||||
homeassistant/components/tikteck/light.py
|
||||
homeassistant/components/tile/__init__.py
|
||||
homeassistant/components/tile/device_tracker.py
|
||||
@@ -886,6 +964,7 @@ omit =
|
||||
homeassistant/components/vesync/__init__.py
|
||||
homeassistant/components/vesync/common.py
|
||||
homeassistant/components/vesync/const.py
|
||||
homeassistant/components/vesync/fan.py
|
||||
homeassistant/components/vesync/switch.py
|
||||
homeassistant/components/viaggiatreno/sensor.py
|
||||
homeassistant/components/vicare/*
|
||||
@@ -896,6 +975,7 @@ omit =
|
||||
homeassistant/components/vlc/media_player.py
|
||||
homeassistant/components/vlc_telnet/media_player.py
|
||||
homeassistant/components/volkszaehler/sensor.py
|
||||
homeassistant/components/volumio/__init__.py
|
||||
homeassistant/components/volumio/media_player.py
|
||||
homeassistant/components/volvooncall/*
|
||||
homeassistant/components/w800rf32/*
|
||||
@@ -910,6 +990,9 @@ omit =
|
||||
homeassistant/components/wiffi/*
|
||||
homeassistant/components/wink/*
|
||||
homeassistant/components/wirelesstag/*
|
||||
homeassistant/components/wolflink/__init__.py
|
||||
homeassistant/components/wolflink/sensor.py
|
||||
homeassistant/components/wolflink/const.py
|
||||
homeassistant/components/worldtidesinfo/sensor.py
|
||||
homeassistant/components/worxlandroid/sensor.py
|
||||
homeassistant/components/x10/light.py
|
||||
@@ -942,7 +1025,6 @@ omit =
|
||||
homeassistant/components/yale_smart_alarm/alarm_control_panel.py
|
||||
homeassistant/components/yamaha_musiccast/media_player.py
|
||||
homeassistant/components/yandex_transport/*
|
||||
homeassistant/components/yeelight/*
|
||||
homeassistant/components/yeelightsunflower/light.py
|
||||
homeassistant/components/yi/camera.py
|
||||
homeassistant/components/zabbix/*
|
||||
@@ -968,11 +1050,9 @@ omit =
|
||||
homeassistant/components/zhong_hong/climate.py
|
||||
homeassistant/components/xbee/*
|
||||
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
||||
homeassistant/components/zoneminder/*
|
||||
homeassistant/components/supla/*
|
||||
homeassistant/components/zwave/util.py
|
||||
homeassistant/components/ozw/__init__.py
|
||||
homeassistant/components/ozw/discovery.py
|
||||
homeassistant/components/ozw/entity.py
|
||||
homeassistant/components/ozw/services.py
|
||||
|
||||
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -16,7 +16,7 @@
|
||||
<!--
|
||||
Provide details about the versions you are using, which helps us to reproduce
|
||||
and find the issue quicker. Version information is found in the
|
||||
Home Assistant frontend: Developer tools -> Info.
|
||||
Home Assistant frontend: Configuration -> Info.
|
||||
-->
|
||||
|
||||
- Home Assistant Core release with the issue:
|
||||
|
2
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
2
.github/ISSUE_TEMPLATE/BUG_REPORT.md
vendored
@@ -20,7 +20,7 @@ about: Report an issue with Home Assistant Core
|
||||
<!--
|
||||
Provide details about the versions you are using, which helps us to reproduce
|
||||
and find the issue quicker. Version information is found in the
|
||||
Home Assistant frontend: Developer tools -> Info.
|
||||
Home Assistant frontend: Configuration -> Info.
|
||||
-->
|
||||
|
||||
- Home Assistant Core release with the issue:
|
||||
|
27
.github/PULL_REQUEST_TEMPLATE.md
vendored
27
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
## Proposed change
|
||||
<!--
|
||||
<!--
|
||||
Describe the big picture of your changes here to communicate to the
|
||||
maintainers why we should accept this pull request. If it fixes a bug
|
||||
or resolves a feature request, be sure to link to that issue in the
|
||||
@@ -24,7 +24,7 @@
|
||||
## Type of change
|
||||
<!--
|
||||
What type of change does your PR introduce to Home Assistant?
|
||||
NOTE: Please, check only 1! box!
|
||||
NOTE: Please, check only 1! box!
|
||||
If your PR requires multiple boxes to be checked, you'll most likely need to
|
||||
split it into multiple PRs. This makes things easier and faster to code review.
|
||||
-->
|
||||
@@ -98,6 +98,29 @@ The integration reached or maintains the following [Integration Quality Scale][q
|
||||
- [ ] 🥇 Gold
|
||||
- [ ] 🏆 Platinum
|
||||
|
||||
<!--
|
||||
This project is very active and we have a high turnover of pull requests.
|
||||
|
||||
Unfortunately, the number of incoming pull requests is higher than what our
|
||||
reviewers can review and merge so there is a long backlog of pull requests
|
||||
waiting for review. You can help here!
|
||||
|
||||
By reviewing another pull request, you will help raise the code quality of
|
||||
that pull request and the final review will be faster. This way the general
|
||||
pace of pull request reviews will go up and your wait time will go down.
|
||||
|
||||
When picking a pull request to review, try to choose one that hasn't yet
|
||||
been reviewed.
|
||||
|
||||
Thanks for helping out!
|
||||
-->
|
||||
|
||||
To help with the load of incoming pull requests:
|
||||
|
||||
- [ ] I have reviewed two other [open pull requests][prs] in this repository.
|
||||
|
||||
[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-asc+-review%3Aapproved
|
||||
|
||||
<!--
|
||||
Thank you for contributing <3
|
||||
|
||||
|
8
.github/dependabot.yml
vendored
Normal file
8
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "06:00"
|
||||
open-pull-requests-limit: 10
|
782
.github/workflows/ci.yaml
vendored
Normal file
782
.github/workflows/ci.yaml
vendored
Normal file
@@ -0,0 +1,782 @@
|
||||
name: CI
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- rc
|
||||
- master
|
||||
pull_request: ~
|
||||
|
||||
env:
|
||||
CACHE_VERSION: 1
|
||||
DEFAULT_PYTHON: 3.7
|
||||
PRE_COMMIT_HOME: ~/.cache/pre-commit
|
||||
|
||||
jobs:
|
||||
# Separate job to pre-populate the base dependency cache
|
||||
# This prevent upcoming jobs to do the same individually
|
||||
prepare-base:
|
||||
name: Prepare base dependencies
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v2.1.2
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
restore-keys: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}-${{ hashFiles('requirements_test.txt') }}-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-${{ hashFiles('requirements.txt') }}
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{ steps.python.outputs.python-version }}-
|
||||
- name: Create Python virtual environment
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
python -m venv venv
|
||||
. venv/bin/activate
|
||||
pip install -U pip setuptools
|
||||
pip install -r requirements.txt -r requirements_test.txt
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-
|
||||
- name: Install pre-commit dependencies
|
||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit install-hooks
|
||||
|
||||
lint-bandit:
|
||||
name: Check bandit
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run bandit
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual bandit --all-files --show-diff-on-failure
|
||||
|
||||
lint-black:
|
||||
name: Check black
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run black
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual black --all-files --show-diff-on-failure
|
||||
|
||||
lint-codespell:
|
||||
name: Check codespell
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register codespell problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/codespell.json"
|
||||
- name: Run codespell
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --show-diff-on-failure --hook-stage manual codespell --all-files
|
||||
|
||||
lint-dockerfile:
|
||||
name: Check Dockerfile
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Register hadolint problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
|
||||
- name: Check Dockerfile
|
||||
uses: docker://hadolint/hadolint:v1.18.0
|
||||
with:
|
||||
args: hadolint Dockerfile
|
||||
- name: Check Dockerfile.dev
|
||||
uses: docker://hadolint/hadolint:v1.18.0
|
||||
with:
|
||||
args: hadolint Dockerfile.dev
|
||||
|
||||
lint-executable-shebangs:
|
||||
name: Check executables
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register check executables problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/check-executables-have-shebangs.json"
|
||||
- name: Run executables check
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual check-executables-have-shebangs --all-files
|
||||
|
||||
lint-flake8:
|
||||
name: Check flake8
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register flake8 problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/flake8.json"
|
||||
- name: Run flake8
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual flake8 --all-files
|
||||
|
||||
lint-isort:
|
||||
name: Check isort
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run isort
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure
|
||||
|
||||
lint-json:
|
||||
name: Check JSON
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register check-json problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/check-json.json"
|
||||
- name: Run check-json
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual check-json --all-files
|
||||
|
||||
lint-pyupgrade:
|
||||
name: Check pyupgrade
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run pyupgrade
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
|
||||
|
||||
# Disabled until we have the existing issues fixed
|
||||
# lint-shellcheck:
|
||||
# name: Check ShellCheck
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: prepare-base
|
||||
# steps:
|
||||
# - name: Check out code from GitHub
|
||||
# uses: actions/checkout@v2
|
||||
# - name: Run ShellCheck
|
||||
# uses: ludeeus/action-shellcheck@0.3.0
|
||||
|
||||
lint-yaml:
|
||||
name: Check YAML
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_HOME }}
|
||||
key: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
- name: Fail job if cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register yamllint problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/yamllint.json"
|
||||
- name: Run yamllint
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pre-commit run --hook-stage manual yamllint --all-files --show-diff-on-failure
|
||||
|
||||
hassfest:
|
||||
name: Check hassfest
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-tests
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name:
|
||||
Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run hassfest
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
python -m script.hassfest --requirements --action validate
|
||||
|
||||
gen-requirements-all:
|
||||
name: Check all requirements
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v2.1.2
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-base-venv-${{
|
||||
steps.python.outputs.python-version }}-${{
|
||||
hashFiles('requirements.txt') }}-${{
|
||||
hashFiles('requirements_test.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Run gen_requirements_all.py
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
python -m script.gen_requirements_all validate
|
||||
|
||||
prepare-tests:
|
||||
name: Prepare tests for Python ${{ matrix.python-version }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7, 3.8]
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
restore-keys: |
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }}-${{ hashFiles('requirements_all.txt') }}
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-${{ hashFiles('requirements_test.txt') }}
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{ matrix.python-version }}-
|
||||
- name: Create full Python ${{ matrix.python-version }} virtual environment
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
python -m venv venv
|
||||
. venv/bin/activate
|
||||
pip install -U pip setuptools wheel
|
||||
pip install -r requirements_all.txt
|
||||
pip install -r requirements_test.txt
|
||||
pip install -e .
|
||||
|
||||
pylint:
|
||||
name: Check pylint
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-tests
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register pylint problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/pylint.json"
|
||||
- name: Run pylint
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pylint homeassistant
|
||||
|
||||
mypy:
|
||||
name: Check mypy
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-tests
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register mypy problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/mypy.json"
|
||||
- name: Run mypy
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
mypy homeassistant
|
||||
|
||||
pytest:
|
||||
runs-on: ubuntu-latest
|
||||
needs: prepare-tests
|
||||
strategy:
|
||||
matrix:
|
||||
group: [1, 2, 3, 4]
|
||||
python-version: [3.7, 3.8]
|
||||
name: >-
|
||||
Run tests Python ${{ matrix.python-version }} (group ${{ matrix.group }})
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Register Python problem matcher
|
||||
run: |
|
||||
echo "::add-matcher::.github/workflows/matchers/python.json"
|
||||
- name: Install Pytest Annotation plugin
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
# Ideally this should be part of our dependencies
|
||||
# However this plugin is fairly new and doesn't run correctly
|
||||
# on a non-GitHub environment.
|
||||
pip install pytest-github-actions-annotate-failures
|
||||
- name: Run pytest
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
pytest \
|
||||
-qq \
|
||||
--timeout=9 \
|
||||
--durations=10 \
|
||||
-n auto \
|
||||
--dist=loadfile \
|
||||
--test-group-count 4 \
|
||||
--test-group=${{ matrix.group }} \
|
||||
--cov homeassistant \
|
||||
-o console_output_style=count \
|
||||
-p no:sugar \
|
||||
tests
|
||||
- name: Upload coverage artifact
|
||||
uses: actions/upload-artifact@v2.1.4
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-group${{ matrix.group }}
|
||||
path: .coverage
|
||||
- name: Check dirty
|
||||
run: |
|
||||
./script/check_dirty
|
||||
|
||||
coverage:
|
||||
name: Process test coverage
|
||||
runs-on: ubuntu-latest
|
||||
needs: pytest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [3.7]
|
||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v2
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
${{ env.CACHE_VERSION}}-${{ runner.os }}-venv-${{
|
||||
matrix.python-version }}-${{ hashFiles('requirements_test.txt')
|
||||
}}-${{ hashFiles('requirements_all.txt') }}-${{
|
||||
hashFiles('homeassistant/package_constraints.txt') }}
|
||||
- name: Fail job if Python cache restore failed
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
echo "Failed to restore Python virtual environment from cache"
|
||||
exit 1
|
||||
- name: Download all coverage artifacts
|
||||
uses: actions/download-artifact@v2
|
||||
- name: Combine coverage results
|
||||
run: |
|
||||
. venv/bin/activate
|
||||
coverage combine coverage*/.coverage*
|
||||
coverage report --fail-under=94
|
||||
coverage xml
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v1.0.13
|
14
.github/workflows/matchers/check-executables-have-shebangs.json
vendored
Normal file
14
.github/workflows/matchers/check-executables-have-shebangs.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "check-executables-have-shebangs",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):\\s(.+)$",
|
||||
"file": 1,
|
||||
"message": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
16
.github/workflows/matchers/check-json.json
vendored
Normal file
16
.github/workflows/matchers/check-json.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "check-json",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):\\s(.+\\sline\\s(\\d+)\\scolumn\\s(\\d+).+)$",
|
||||
"file": 1,
|
||||
"message": 2,
|
||||
"line": 3,
|
||||
"column": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
16
.github/workflows/matchers/codespell.json
vendored
Normal file
16
.github/workflows/matchers/codespell.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "codespell",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):\\s(.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
30
.github/workflows/matchers/flake8.json
vendored
Normal file
30
.github/workflows/matchers/flake8.json
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "flake8-error",
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*):(\\d+):(\\d+):\\s([EF]\\d{3}\\s.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "flake8-warning",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*):(\\d+):(\\d+):\\s([CDNW]\\d{3}\\s.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
16
.github/workflows/matchers/hadolint.json
vendored
Normal file
16
.github/workflows/matchers/hadolint.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "hadolint",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+)\\s+((DL\\d{4}).+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3,
|
||||
"code": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
16
.github/workflows/matchers/mypy.json
vendored
Normal file
16
.github/workflows/matchers/mypy.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "mypy",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):\\s(error|warning):\\s(.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"severity": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
32
.github/workflows/matchers/pylint.json
vendored
Normal file
32
.github/workflows/matchers/pylint.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "pylint-error",
|
||||
"severity": "error",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):(\\d+):\\s(([EF]\\d{4}):\\s.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4,
|
||||
"code": 5
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"owner": "pylint-warning",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):(\\d+):\\s(([CRW]\\d{4}):\\s.+)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4,
|
||||
"code": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
18
.github/workflows/matchers/python.json
vendored
Normal file
18
.github/workflows/matchers/python.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "python",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^\\s*File\\s\\\"(.*)\\\",\\sline\\s(\\d+),\\sin\\s(.*)$",
|
||||
"file": 1,
|
||||
"line": 2
|
||||
},
|
||||
{
|
||||
"regexp": "^\\s*raise\\s(.*)\\(\\'(.*)\\'\\)$",
|
||||
"message": 2
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
22
.github/workflows/matchers/yamllint.json
vendored
Normal file
22
.github/workflows/matchers/yamllint.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "yamllint",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.*\\.ya?ml)$",
|
||||
"file": 1
|
||||
},
|
||||
{
|
||||
"regexp": "^\\s{2}(\\d+):(\\d+)\\s+(error|warning)\\s+(.*?)\\s+\\((.*)\\)$",
|
||||
"line": 1,
|
||||
"column": 2,
|
||||
"severity": 3,
|
||||
"message": 4,
|
||||
"code": 5,
|
||||
"loop": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -1,11 +1,11 @@
|
||||
repos:
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.3.0
|
||||
rev: v2.7.2
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py37-plus]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 19.10b0
|
||||
rev: 20.8b1
|
||||
hooks:
|
||||
- id: black
|
||||
args:
|
||||
@@ -13,21 +13,21 @@ repos:
|
||||
- --quiet
|
||||
files: ^((homeassistant|script|tests)/.+)?[^/]+\.py$
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v1.16.0
|
||||
rev: v1.17.1
|
||||
hooks:
|
||||
- id: codespell
|
||||
args:
|
||||
- --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing
|
||||
- --ignore-words-list=hass,alot,datas,dof,dur,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,iam,incomfort
|
||||
- --skip="./.*,*.csv,*.json"
|
||||
- --quiet-level=2
|
||||
exclude_types: [csv, json]
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.1
|
||||
rev: 3.8.3
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies:
|
||||
- flake8-docstrings==1.5.0
|
||||
- pydocstyle==5.0.2
|
||||
- pydocstyle==5.1.1
|
||||
files: ^(homeassistant|script|tests)/.+\.py$
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: 1.6.2
|
||||
@@ -38,12 +38,12 @@ repos:
|
||||
- --format=custom
|
||||
- --configfile=tests/bandit.yaml
|
||||
files: ^(homeassistant|script|tests)/.+\.py$
|
||||
- repo: https://github.com/pre-commit/mirrors-isort
|
||||
rev: v4.3.21
|
||||
- repo: https://github.com/PyCQA/isort
|
||||
rev: 5.5.3
|
||||
hooks:
|
||||
- id: isort
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.4.0
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: check-executables-have-shebangs
|
||||
stages: [manual]
|
||||
@@ -54,7 +54,7 @@ repos:
|
||||
- --branch=master
|
||||
- --branch=rc
|
||||
- repo: https://github.com/adrienverge/yamllint.git
|
||||
rev: v1.23.0
|
||||
rev: v1.24.2
|
||||
hooks:
|
||||
- id: yamllint
|
||||
- repo: https://github.com/prettier/prettier
|
||||
|
30
.travis.yml
30
.travis.yml
@@ -1,8 +1,8 @@
|
||||
sudo: false
|
||||
dist: bionic
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- ffmpeg
|
||||
- libudev-dev
|
||||
- libavformat-dev
|
||||
- libavcodec-dev
|
||||
@@ -13,23 +13,33 @@ addons:
|
||||
- libavfilter-dev
|
||||
sources:
|
||||
- sourceline: ppa:savoury1/ffmpeg4
|
||||
- sourceline: ppa:savoury1/multimedia
|
||||
|
||||
matrix:
|
||||
python:
|
||||
- "3.7.1"
|
||||
- "3.8"
|
||||
|
||||
env:
|
||||
- TOX_ARGS="-- --test-group-count 4 --test-group 1"
|
||||
- TOX_ARGS="-- --test-group-count 4 --test-group 2"
|
||||
- TOX_ARGS="-- --test-group-count 4 --test-group 3"
|
||||
- TOX_ARGS="-- --test-group-count 4 --test-group 4"
|
||||
|
||||
jobs:
|
||||
fast_finish: true
|
||||
include:
|
||||
- python: "3.7.0"
|
||||
- python: "3.7.1"
|
||||
env: TOXENV=lint
|
||||
- python: "3.7.0"
|
||||
env: TOXENV=pylint PYLINT_ARGS=--jobs=0 TRAVIS_WAIT=30
|
||||
- python: "3.7.0"
|
||||
- python: "3.7.1"
|
||||
# PYLINT_ARGS=--jobs=0 disabled for now: https://github.com/PyCQA/pylint/issues/3584
|
||||
env: TOXENV=pylint TRAVIS_WAIT=30
|
||||
- python: "3.7.1"
|
||||
env: TOXENV=typing
|
||||
- python: "3.7.0"
|
||||
env: TOXENV=py37
|
||||
|
||||
cache:
|
||||
pip: true
|
||||
directories:
|
||||
- $HOME/.cache/pre-commit
|
||||
install: pip install -U tox
|
||||
install: pip install -U tox tox-travis
|
||||
language: python
|
||||
script: ${TRAVIS_WAIT:+travis_wait $TRAVIS_WAIT} tox --develop
|
||||
script: ${TRAVIS_WAIT:+travis_wait $TRAVIS_WAIT} tox --develop ${TOX_ARGS-}
|
||||
|
4
.vscode/tasks.json
vendored
4
.vscode/tasks.json
vendored
@@ -76,7 +76,7 @@
|
||||
{
|
||||
"label": "Install all Requirements",
|
||||
"type": "shell",
|
||||
"command": "pip3 install -r requirements_all.txt -c homeassistant/package_constraints.txt",
|
||||
"command": "pip3 install -r requirements_all.txt",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
@@ -90,7 +90,7 @@
|
||||
{
|
||||
"label": "Install all Test Requirements",
|
||||
"type": "shell",
|
||||
"command": "pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt",
|
||||
"command": "pip3 install -r requirements_test_all.txt",
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
|
104
CODEOWNERS
104
CODEOWNERS
@@ -14,6 +14,7 @@ homeassistant/scripts/check_config.py @kellerza
|
||||
|
||||
# Integrations
|
||||
homeassistant/components/abode/* @shred86
|
||||
homeassistant/components/accuweather/* @bieniu
|
||||
homeassistant/components/acmeda/* @atmurray
|
||||
homeassistant/components/adguard/* @frenck
|
||||
homeassistant/components/agent_dvr/* @ispysoftware
|
||||
@@ -23,7 +24,6 @@ homeassistant/components/alarmdecoder/* @ajschmidt8
|
||||
homeassistant/components/alexa/* @home-assistant/cloud @ochlocracy
|
||||
homeassistant/components/almond/* @gcampax @balloob
|
||||
homeassistant/components/alpha_vantage/* @fabaff
|
||||
homeassistant/components/amazon_polly/* @robbiet480
|
||||
homeassistant/components/ambiclimate/* @danielhiversen
|
||||
homeassistant/components/ambient_station/* @bachya
|
||||
homeassistant/components/amcrest/* @pnbruckner
|
||||
@@ -47,8 +47,9 @@ homeassistant/components/automation/* @home-assistant/core
|
||||
homeassistant/components/avea/* @pattyland
|
||||
homeassistant/components/avri/* @timvancann
|
||||
homeassistant/components/awair/* @ahayworth @danielsjf
|
||||
homeassistant/components/aws/* @awarecan @robbiet480
|
||||
homeassistant/components/aws/* @awarecan
|
||||
homeassistant/components/axis/* @Kane610
|
||||
homeassistant/components/azure_devops/* @timmo001
|
||||
homeassistant/components/azure_event_hub/* @eavanvalkenburg
|
||||
homeassistant/components/azure_service_bus/* @hfurubotten
|
||||
homeassistant/components/beewi_smartclim/* @alemuro
|
||||
@@ -59,7 +60,8 @@ homeassistant/components/blink/* @fronzbot
|
||||
homeassistant/components/bmp280/* @belidzs
|
||||
homeassistant/components/bmw_connected_drive/* @gerard33 @rikroe
|
||||
homeassistant/components/bom/* @maddenp
|
||||
homeassistant/components/braviatv/* @robbiet480 @bieniu
|
||||
homeassistant/components/bond/* @prystupa
|
||||
homeassistant/components/braviatv/* @bieniu
|
||||
homeassistant/components/broadlink/* @danielhiversen @felipediel
|
||||
homeassistant/components/brother/* @bieniu
|
||||
homeassistant/components/brunt/* @eavanvalkenburg
|
||||
@@ -77,6 +79,7 @@ homeassistant/components/cloudflare/* @ludeeus
|
||||
homeassistant/components/comfoconnect/* @michaelarnauts
|
||||
homeassistant/components/config/* @home-assistant/core
|
||||
homeassistant/components/configurator/* @home-assistant/core
|
||||
homeassistant/components/control4/* @lawtancool
|
||||
homeassistant/components/conversation/* @home-assistant/core
|
||||
homeassistant/components/coolmaster/* @OnFreund
|
||||
homeassistant/components/coronavirus/* @home_assistant/core
|
||||
@@ -94,25 +97,30 @@ homeassistant/components/denonavr/* @scarface-4711 @starkillerOG
|
||||
homeassistant/components/derivative/* @afaucogney
|
||||
homeassistant/components/device_automation/* @home-assistant/core
|
||||
homeassistant/components/devolo_home_control/* @2Fake @Shutgun
|
||||
homeassistant/components/dexcom/* @gagebenne
|
||||
homeassistant/components/digital_ocean/* @fabaff
|
||||
homeassistant/components/directv/* @ctalkington
|
||||
homeassistant/components/discogs/* @thibmaek
|
||||
homeassistant/components/doorbird/* @oblogic7 @bdraco
|
||||
homeassistant/components/dsmr/* @Robbie1221
|
||||
homeassistant/components/dsmr_reader/* @depl0y
|
||||
homeassistant/components/dunehd/* @bieniu
|
||||
homeassistant/components/dwd_weather_warnings/* @runningman84 @stephan192 @Hummel95
|
||||
homeassistant/components/dweet/* @fabaff
|
||||
homeassistant/components/dynalite/* @ziv1234
|
||||
homeassistant/components/dyson/* @etheralm
|
||||
homeassistant/components/eafm/* @Jc2k
|
||||
homeassistant/components/ecobee/* @marthoc
|
||||
homeassistant/components/ecovacs/* @OverloadUT
|
||||
homeassistant/components/edl21/* @mtdcr
|
||||
homeassistant/components/egardia/* @jeroenterheerdt
|
||||
homeassistant/components/eight_sleep/* @mezz64
|
||||
homeassistant/components/elgato/* @frenck
|
||||
homeassistant/components/elkm1/* @bdraco
|
||||
homeassistant/components/elkm1/* @gwww @bdraco
|
||||
homeassistant/components/elv/* @majuss
|
||||
homeassistant/components/emby/* @mezz64
|
||||
homeassistant/components/emoncms/* @borpin
|
||||
homeassistant/components/emulated_kasa/* @kbickar
|
||||
homeassistant/components/enigma2/* @fbradyirl
|
||||
homeassistant/components/enocean/* @bdurrer
|
||||
homeassistant/components/entur_public_transport/* @hfurubotten
|
||||
@@ -127,16 +135,16 @@ homeassistant/components/ezviz/* @baqs
|
||||
homeassistant/components/fastdotcom/* @rohankapoorcom
|
||||
homeassistant/components/file/* @fabaff
|
||||
homeassistant/components/filter/* @dgomes
|
||||
homeassistant/components/fitbit/* @robbiet480
|
||||
homeassistant/components/firmata/* @DaAwesomeP
|
||||
homeassistant/components/fixer/* @fabaff
|
||||
homeassistant/components/flick_electric/* @ZephireNZ
|
||||
homeassistant/components/flo/* @dmulcahey
|
||||
homeassistant/components/flock/* @fabaff
|
||||
homeassistant/components/flume/* @ChrisMandich @bdraco
|
||||
homeassistant/components/flunearyou/* @bachya
|
||||
homeassistant/components/forked_daapd/* @uvjustin
|
||||
homeassistant/components/fortios/* @kimfrellsen
|
||||
homeassistant/components/foscam/* @skgsergio
|
||||
homeassistant/components/foursquare/* @robbiet480
|
||||
homeassistant/components/freebox/* @snoof85 @Quentame
|
||||
homeassistant/components/fronius/* @nielstron
|
||||
homeassistant/components/frontend/* @home-assistant/frontend
|
||||
@@ -149,21 +157,20 @@ homeassistant/components/geonetnz_volcano/* @exxamalte
|
||||
homeassistant/components/gios/* @bieniu
|
||||
homeassistant/components/gitter/* @fabaff
|
||||
homeassistant/components/glances/* @fabaff @engrbm87
|
||||
homeassistant/components/gntp/* @robbiet480
|
||||
homeassistant/components/goalzero/* @tkdrob
|
||||
homeassistant/components/gogogate2/* @vangorra
|
||||
homeassistant/components/google_assistant/* @home-assistant/cloud
|
||||
homeassistant/components/google_cloud/* @lufton
|
||||
homeassistant/components/google_translate/* @awarecan
|
||||
homeassistant/components/google_travel_time/* @robbiet480
|
||||
homeassistant/components/gpsd/* @fabaff
|
||||
homeassistant/components/greeneye_monitor/* @jkeljo
|
||||
homeassistant/components/griddy/* @bdraco
|
||||
homeassistant/components/group/* @home-assistant/core
|
||||
homeassistant/components/growatt_server/* @indykoning
|
||||
homeassistant/components/gtfs/* @robbiet480
|
||||
homeassistant/components/guardian/* @bachya
|
||||
homeassistant/components/harmony/* @ehendrix23 @bramkragten @bdraco
|
||||
homeassistant/components/hassio/* @home-assistant/hass-io
|
||||
homeassistant/components/hdmi_cec/* @newAM
|
||||
homeassistant/components/heatmiser/* @andylockran
|
||||
homeassistant/components/heos/* @andrewsayre
|
||||
homeassistant/components/here_travel_time/* @eifinger
|
||||
@@ -172,6 +179,7 @@ homeassistant/components/hikvisioncam/* @fbradyirl
|
||||
homeassistant/components/hisense_aehw4a1/* @bannhead
|
||||
homeassistant/components/history/* @home-assistant/core
|
||||
homeassistant/components/hive/* @Rendili @KJonline
|
||||
homeassistant/components/hlk_sw16/* @jameshilliard
|
||||
homeassistant/components/home_connect/* @DavidMStraub
|
||||
homeassistant/components/homeassistant/* @home-assistant/core
|
||||
homeassistant/components/homekit/* @bdraco
|
||||
@@ -179,21 +187,22 @@ homeassistant/components/homekit_controller/* @Jc2k
|
||||
homeassistant/components/homematic/* @pvizeli @danielperna84
|
||||
homeassistant/components/homematicip_cloud/* @SukramJ
|
||||
homeassistant/components/honeywell/* @zxdavb
|
||||
homeassistant/components/html5/* @robbiet480
|
||||
homeassistant/components/http/* @home-assistant/core
|
||||
homeassistant/components/huawei_lte/* @scop @fphammerle
|
||||
homeassistant/components/huawei_router/* @abmantis
|
||||
homeassistant/components/hue/* @balloob
|
||||
homeassistant/components/hue/* @balloob @frenck
|
||||
homeassistant/components/humidifier/* @home-assistant/core @Shulyaka
|
||||
homeassistant/components/hunterdouglas_powerview/* @bdraco
|
||||
homeassistant/components/hvv_departures/* @vigonotion
|
||||
homeassistant/components/hydrawise/* @ptcryan
|
||||
homeassistant/components/hyperion/* @dermotduffy
|
||||
homeassistant/components/iammeter/* @lewei50
|
||||
homeassistant/components/iaqualink/* @flz
|
||||
homeassistant/components/icloud/* @Quentame
|
||||
homeassistant/components/ign_sismologia/* @exxamalte
|
||||
homeassistant/components/image/* @home-assistant/core
|
||||
homeassistant/components/incomfort/* @zxdavb
|
||||
homeassistant/components/influxdb/* @fabaff
|
||||
homeassistant/components/influxdb/* @fabaff @mdegat01
|
||||
homeassistant/components/input_boolean/* @home-assistant/core
|
||||
homeassistant/components/input_datetime/* @home-assistant/core
|
||||
homeassistant/components/input_number/* @home-assistant/core
|
||||
@@ -219,20 +228,20 @@ homeassistant/components/keba/* @dannerph
|
||||
homeassistant/components/keenetic_ndms2/* @foxel
|
||||
homeassistant/components/kef/* @basnijholt
|
||||
homeassistant/components/keyboard_remote/* @bendavid
|
||||
homeassistant/components/knx/* @Julius2342
|
||||
homeassistant/components/kodi/* @armills
|
||||
homeassistant/components/knx/* @Julius2342 @farmio @marvin-w
|
||||
homeassistant/components/kodi/* @OnFreund @cgtobi
|
||||
homeassistant/components/konnected/* @heythisisnate @kit-klein
|
||||
homeassistant/components/lametric/* @robbiet480
|
||||
homeassistant/components/launch_library/* @ludeeus
|
||||
homeassistant/components/lcn/* @alengwenus
|
||||
homeassistant/components/life360/* @pnbruckner
|
||||
homeassistant/components/linky/* @Quentame
|
||||
homeassistant/components/linux_battery/* @fabaff
|
||||
homeassistant/components/local_ip/* @issacg
|
||||
homeassistant/components/logger/* @home-assistant/core
|
||||
homeassistant/components/logi_circle/* @evanjd
|
||||
homeassistant/components/loopenergy/* @pavoni
|
||||
homeassistant/components/lovelace/* @home-assistant/frontend
|
||||
homeassistant/components/luci/* @fbradyirl @mzdrale
|
||||
homeassistant/components/luci/* @mzdrale
|
||||
homeassistant/components/luftdaten/* @fabaff
|
||||
homeassistant/components/lupusec/* @majuss
|
||||
homeassistant/components/lutron/* @JonGilmore
|
||||
@@ -240,21 +249,22 @@ homeassistant/components/lutron_caseta/* @swails
|
||||
homeassistant/components/mastodon/* @fabaff
|
||||
homeassistant/components/matrix/* @tinloaf
|
||||
homeassistant/components/mcp23017/* @jardiamj
|
||||
homeassistant/components/media_source/* @hunterjm
|
||||
homeassistant/components/mediaroom/* @dgomes
|
||||
homeassistant/components/melcloud/* @vilppuvuorinen
|
||||
homeassistant/components/melissa/* @kennedyshead
|
||||
homeassistant/components/met/* @danielhiversen
|
||||
homeassistant/components/meteo_france/* @victorcerutti @oncleben31 @Quentame
|
||||
homeassistant/components/met/* @danielhiversen @thimic
|
||||
homeassistant/components/meteo_france/* @hacf-fr @oncleben31 @Quentame
|
||||
homeassistant/components/meteoalarm/* @rolfberkenbosch
|
||||
homeassistant/components/metoffice/* @MrHarcombe
|
||||
homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel
|
||||
homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel @basnijholt
|
||||
homeassistant/components/mikrotik/* @engrbm87
|
||||
homeassistant/components/mill/* @danielhiversen
|
||||
homeassistant/components/min_max/* @fabaff
|
||||
homeassistant/components/minecraft_server/* @elmurato
|
||||
homeassistant/components/minio/* @tkislan
|
||||
homeassistant/components/mobile_app/* @robbiet480
|
||||
homeassistant/components/modbus/* @adamchengtkc @janiversen
|
||||
homeassistant/components/modbus/* @adamchengtkc @janiversen @vzahradnik
|
||||
homeassistant/components/monoprice/* @etsinko @OnFreund
|
||||
homeassistant/components/moon/* @fabaff
|
||||
homeassistant/components/mpd/* @fabaff
|
||||
@@ -273,17 +283,19 @@ homeassistant/components/netdata/* @fabaff
|
||||
homeassistant/components/nexia/* @ryannazaretian @bdraco
|
||||
homeassistant/components/nextbus/* @vividboarder
|
||||
homeassistant/components/nextcloud/* @meichthys
|
||||
homeassistant/components/nightscout/* @marciogranzotto
|
||||
homeassistant/components/nilu/* @hfurubotten
|
||||
homeassistant/components/nissan_leaf/* @filcole
|
||||
homeassistant/components/nmbs/* @thibmaek
|
||||
homeassistant/components/no_ip/* @fabaff
|
||||
homeassistant/components/noaa_tides/* @jdelaney72
|
||||
homeassistant/components/notify/* @home-assistant/core
|
||||
homeassistant/components/notify_events/* @matrozov @papajojo
|
||||
homeassistant/components/notion/* @bachya
|
||||
homeassistant/components/nsw_fuel_station/* @nickw444
|
||||
homeassistant/components/nsw_rural_fire_service_feed/* @exxamalte
|
||||
homeassistant/components/nuheat/* @bdraco
|
||||
homeassistant/components/nuki/* @pvizeli
|
||||
homeassistant/components/nuki/* @pschmitt @pvizeli
|
||||
homeassistant/components/numato/* @clssn
|
||||
homeassistant/components/nut/* @bdraco
|
||||
homeassistant/components/nws/* @MatthewFlamm
|
||||
@@ -291,6 +303,7 @@ homeassistant/components/nzbget/* @chriscla
|
||||
homeassistant/components/obihai/* @dshokouhi
|
||||
homeassistant/components/ohmconnect/* @robbiet480
|
||||
homeassistant/components/ombi/* @larssont
|
||||
homeassistant/components/omnilogic/* @oliver84 @djtimca @gentoosu
|
||||
homeassistant/components/onboarding/* @home-assistant/core
|
||||
homeassistant/components/onewire/* @garbled1
|
||||
homeassistant/components/onvif/* @hunterjm
|
||||
@@ -298,10 +311,11 @@ homeassistant/components/openerz/* @misialq
|
||||
homeassistant/components/opengarage/* @danielhiversen
|
||||
homeassistant/components/opentherm_gw/* @mvn23
|
||||
homeassistant/components/openuv/* @bachya
|
||||
homeassistant/components/openweathermap/* @fabaff
|
||||
homeassistant/components/openweathermap/* @fabaff @freekode
|
||||
homeassistant/components/opnsense/* @mtreinish
|
||||
homeassistant/components/orangepi_gpio/* @pascallj
|
||||
homeassistant/components/oru/* @bvlaicu
|
||||
homeassistant/components/ovo_energy/* @timmo001
|
||||
homeassistant/components/ozw/* @cgarwood @marcelveldt @MartinHjelmare
|
||||
homeassistant/components/panasonic_viera/* @joogps
|
||||
homeassistant/components/panel_custom/* @home-assistant/frontend
|
||||
@@ -318,7 +332,9 @@ homeassistant/components/plex/* @jjlawren
|
||||
homeassistant/components/plugwise/* @CoMPaTech @bouwew
|
||||
homeassistant/components/plum_lightpad/* @ColinHarrington @prystupa
|
||||
homeassistant/components/point/* @fredrike
|
||||
homeassistant/components/poolsense/* @haemishkyd
|
||||
homeassistant/components/powerwall/* @bdraco @jrester
|
||||
homeassistant/components/progettihwsw/* @ardaseremet
|
||||
homeassistant/components/prometheus/* @knyar
|
||||
homeassistant/components/proxmoxve/* @k4ds3 @jhollowe
|
||||
homeassistant/components/ps4/* @ktnrg45
|
||||
@@ -337,12 +353,16 @@ homeassistant/components/raincloud/* @vanstinator
|
||||
homeassistant/components/rainforest_eagle/* @gtdiehl @jcalbert
|
||||
homeassistant/components/rainmachine/* @bachya
|
||||
homeassistant/components/random/* @fabaff
|
||||
homeassistant/components/rejseplanen/* @DarkFox
|
||||
homeassistant/components/repetier/* @MTrab
|
||||
homeassistant/components/rfxtrx/* @danielhiversen
|
||||
homeassistant/components/rfxtrx/* @danielhiversen @elupus
|
||||
homeassistant/components/ring/* @balloob
|
||||
homeassistant/components/risco/* @OnFreund
|
||||
homeassistant/components/rmvtransport/* @cgtobi
|
||||
homeassistant/components/roku/* @ctalkington
|
||||
homeassistant/components/roomba/* @pschmitt @cyr-ius @shenxn
|
||||
homeassistant/components/roon/* @pavoni
|
||||
homeassistant/components/rpi_power/* @shenxn @swetoast
|
||||
homeassistant/components/safe_mode/* @home-assistant/core
|
||||
homeassistant/components/saj/* @fredericvl
|
||||
homeassistant/components/salt/* @bjornorri
|
||||
@@ -354,11 +374,13 @@ homeassistant/components/script/* @home-assistant/core
|
||||
homeassistant/components/search/* @home-assistant/core
|
||||
homeassistant/components/sense/* @kbickar
|
||||
homeassistant/components/sensibo/* @andrey-git
|
||||
homeassistant/components/sentry/* @dcramer
|
||||
homeassistant/components/sentry/* @dcramer @frenck
|
||||
homeassistant/components/serial/* @fabaff
|
||||
homeassistant/components/seven_segments/* @fabaff
|
||||
homeassistant/components/seventeentrack/* @bachya
|
||||
homeassistant/components/sharkiq/* @ajmarks
|
||||
homeassistant/components/shell_command/* @home-assistant/core
|
||||
homeassistant/components/shelly/* @balloob @bieniu
|
||||
homeassistant/components/shiftr/* @fabaff
|
||||
homeassistant/components/shodan/* @fabaff
|
||||
homeassistant/components/sighthound/* @robmarkcole
|
||||
@@ -366,9 +388,11 @@ homeassistant/components/signal_messenger/* @bbernhard
|
||||
homeassistant/components/simplisafe/* @bachya
|
||||
homeassistant/components/sinch/* @bendikrb
|
||||
homeassistant/components/sisyphus/* @jkeljo
|
||||
homeassistant/components/sky_hub/* @rogerselwyn
|
||||
homeassistant/components/slide/* @ualex73
|
||||
homeassistant/components/sma/* @kellerza
|
||||
homeassistant/components/smappee/* @bsmappee
|
||||
homeassistant/components/smart_meter_texas/* @grahamwetzler
|
||||
homeassistant/components/smarthab/* @outadoc
|
||||
homeassistant/components/smartthings/* @andrewsayre
|
||||
homeassistant/components/smarty/* @z0mbieprocess
|
||||
@@ -381,9 +405,11 @@ homeassistant/components/soma/* @ratsept
|
||||
homeassistant/components/somfy/* @tetienne
|
||||
homeassistant/components/sonarr/* @ctalkington
|
||||
homeassistant/components/songpal/* @rytilahti @shenxn
|
||||
homeassistant/components/sonos/* @cgtobi
|
||||
homeassistant/components/spaceapi/* @fabaff
|
||||
homeassistant/components/speedtestdotnet/* @rohankapoorcom @engrbm87
|
||||
homeassistant/components/spider/* @peternijssen
|
||||
homeassistant/components/splunk/* @Bre77
|
||||
homeassistant/components/spotify/* @frenck
|
||||
homeassistant/components/sql/* @dgomes
|
||||
homeassistant/components/squeezebox/* @rajlaud
|
||||
@@ -391,7 +417,7 @@ homeassistant/components/starline/* @anonym-tsk
|
||||
homeassistant/components/statistics/* @fabaff
|
||||
homeassistant/components/stiebel_eltron/* @fucm
|
||||
homeassistant/components/stookalert/* @fwestenberg
|
||||
homeassistant/components/stream/* @hunterjm
|
||||
homeassistant/components/stream/* @hunterjm @uvjustin
|
||||
homeassistant/components/stt/* @pvizeli
|
||||
homeassistant/components/suez_water/* @ooii
|
||||
homeassistant/components/sun/* @Swamp-Ig
|
||||
@@ -403,10 +429,11 @@ homeassistant/components/switchbot/* @danielhiversen
|
||||
homeassistant/components/switcher_kis/* @tomerfi
|
||||
homeassistant/components/switchmate/* @danielhiversen
|
||||
homeassistant/components/syncthru/* @nielstron
|
||||
homeassistant/components/synology_dsm/* @ProtoThis @Quentame
|
||||
homeassistant/components/synology_dsm/* @hacf-fr @Quentame
|
||||
homeassistant/components/synology_srm/* @aerialls
|
||||
homeassistant/components/syslog/* @fabaff
|
||||
homeassistant/components/tado/* @michaelarnauts @bdraco
|
||||
homeassistant/components/tag/* @balloob @dmulcahey
|
||||
homeassistant/components/tahoma/* @philklei
|
||||
homeassistant/components/tankerkoenig/* @guillempages
|
||||
homeassistant/components/tautulli/* @ludeeus
|
||||
@@ -427,17 +454,16 @@ homeassistant/components/tplink/* @rytilahti
|
||||
homeassistant/components/traccar/* @ludeeus
|
||||
homeassistant/components/tradfri/* @ggravlingen
|
||||
homeassistant/components/trafikverket_train/* @endor-force
|
||||
homeassistant/components/trafikverket_weatherstation/* @endor-force
|
||||
homeassistant/components/transmission/* @engrbm87 @JPHutchins
|
||||
homeassistant/components/tts/* @pvizeli
|
||||
homeassistant/components/tuya/* @ollo69
|
||||
homeassistant/components/twentemilieu/* @frenck
|
||||
homeassistant/components/twilio_call/* @robbiet480
|
||||
homeassistant/components/twilio_sms/* @robbiet480
|
||||
homeassistant/components/ubee/* @mzdrale
|
||||
homeassistant/components/unifi/* @Kane610
|
||||
homeassistant/components/unifiled/* @florisvdk
|
||||
homeassistant/components/upb/* @gwww
|
||||
homeassistant/components/upc_connect/* @pvizeli
|
||||
homeassistant/components/upc_connect/* @pvizeli @fabaff
|
||||
homeassistant/components/upcloud/* @scop
|
||||
homeassistant/components/updater/* @home-assistant/core
|
||||
homeassistant/components/upnp/* @StevenLooman
|
||||
@@ -448,41 +474,45 @@ homeassistant/components/velbus/* @Cereal2nd @brefra
|
||||
homeassistant/components/velux/* @Julius2342
|
||||
homeassistant/components/vera/* @vangorra
|
||||
homeassistant/components/versasense/* @flamm3blemuff1n
|
||||
homeassistant/components/version/* @fabaff
|
||||
homeassistant/components/vesync/* @markperdue @webdjoe
|
||||
homeassistant/components/version/* @fabaff @ludeeus
|
||||
homeassistant/components/vesync/* @markperdue @webdjoe @thegardenmonkey
|
||||
homeassistant/components/vicare/* @oischinger
|
||||
homeassistant/components/vilfo/* @ManneW
|
||||
homeassistant/components/vivotek/* @HarlemSquirrel
|
||||
homeassistant/components/vizio/* @raman325
|
||||
homeassistant/components/vlc_telnet/* @rodripf
|
||||
homeassistant/components/volkszaehler/* @fabaff
|
||||
homeassistant/components/volumio/* @OnFreund
|
||||
homeassistant/components/waqi/* @andrey-git
|
||||
homeassistant/components/watson_tts/* @rutkai
|
||||
homeassistant/components/weather/* @fabaff
|
||||
homeassistant/components/webostv/* @bendavid
|
||||
homeassistant/components/websocket_api/* @home-assistant/core
|
||||
homeassistant/components/wiffi/* @mampfes
|
||||
homeassistant/components/wilight/* @leofig-rj
|
||||
homeassistant/components/withings/* @vangorra
|
||||
homeassistant/components/wled/* @frenck
|
||||
homeassistant/components/wolflink/* @adamkrol93
|
||||
homeassistant/components/workday/* @fabaff
|
||||
homeassistant/components/worldclock/* @fabaff
|
||||
homeassistant/components/xbox_live/* @MartinHjelmare
|
||||
homeassistant/components/xfinity/* @cisasteelersfan
|
||||
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi
|
||||
homeassistant/components/xiaomi_miio/* @rytilahti @syssi
|
||||
homeassistant/components/xiaomi_miio/* @rytilahti @syssi @starkillerOG
|
||||
homeassistant/components/xiaomi_tv/* @simse
|
||||
homeassistant/components/xmpp/* @fabaff @flowolf
|
||||
homeassistant/components/yamaha_musiccast/* @jalmeroth
|
||||
homeassistant/components/yandex_transport/* @rishatik92
|
||||
homeassistant/components/yeelight/* @rytilahti @zewelor
|
||||
homeassistant/components/yandex_transport/* @rishatik92 @devbis
|
||||
homeassistant/components/yeelight/* @rytilahti @zewelor @shenxn
|
||||
homeassistant/components/yeelightsunflower/* @lindsaymarkward
|
||||
homeassistant/components/yessssms/* @flowolf
|
||||
homeassistant/components/yi/* @bachya
|
||||
homeassistant/components/yr/* @danielhiversen
|
||||
homeassistant/components/zeroconf/* @robbiet480 @Kane610
|
||||
homeassistant/components/zeroconf/* @Kane610
|
||||
homeassistant/components/zerproc/* @emlove
|
||||
homeassistant/components/zha/* @dmulcahey @adminiuga
|
||||
homeassistant/components/zodiac/* @JulienTant
|
||||
homeassistant/components/zone/* @home-assistant/core
|
||||
homeassistant/components/zoneminder/* @rohankapoorcom
|
||||
homeassistant/components/zoneminder/* @rohankapoorcom @vangorra
|
||||
homeassistant/components/zwave/* @home-assistant/z-wave
|
||||
|
||||
# Individual files
|
||||
|
@@ -10,9 +10,9 @@ WORKDIR /usr/src
|
||||
COPY . homeassistant/
|
||||
RUN \
|
||||
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||
-r homeassistant/requirements_all.txt -c homeassistant/homeassistant/package_constraints.txt \
|
||||
-r homeassistant/requirements_all.txt \
|
||||
&& pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||
-e ./homeassistant \
|
||||
-e ./homeassistant \
|
||||
&& python3 -m compileall homeassistant/homeassistant
|
||||
|
||||
# Home Assistant S6-Overlay
|
||||
|
@@ -23,9 +23,10 @@ RUN git clone --depth 1 https://github.com/home-assistant/hass-release \
|
||||
WORKDIR /workspaces
|
||||
|
||||
# Install Python dependencies from requirements
|
||||
COPY requirements_test.txt requirements_test_pre_commit.txt homeassistant/package_constraints.txt ./
|
||||
RUN pip3 install -r requirements_test.txt -c package_constraints.txt \
|
||||
&& rm -f requirements_test.txt package_constraints.txt requirements_test_pre_commit.txt
|
||||
COPY requirements_test.txt requirements_test_pre_commit.txt ./
|
||||
COPY homeassistant/package_constraints.txt homeassistant/package_constraints.txt
|
||||
RUN pip3 install -r requirements_test.txt \
|
||||
&& rm -rf requirements_test.txt requirements_test_pre_commit.txt homeassistant/
|
||||
|
||||
# Set the default shell to bash instead of sh
|
||||
ENV SHELL /bin/bash
|
||||
|
@@ -44,7 +44,7 @@ stages:
|
||||
python -m venv venv
|
||||
|
||||
. venv/bin/activate
|
||||
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
|
||||
pip install -r requirements_test.txt
|
||||
pre-commit install-hooks
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
@@ -117,7 +117,7 @@ stages:
|
||||
python -m venv venv
|
||||
|
||||
. venv/bin/activate
|
||||
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
|
||||
pip install -r requirements_test.txt
|
||||
pre-commit install-hooks
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
@@ -165,10 +165,7 @@ stages:
|
||||
|
||||
. venv/bin/activate
|
||||
pip install -U pip setuptools pytest-azurepipelines pytest-xdist -c homeassistant/package_constraints.txt
|
||||
pip install -r requirements_test_all.txt -c homeassistant/package_constraints.txt
|
||||
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
|
||||
# Find offending deps with `pipdeptree -r -p typing`
|
||||
pip uninstall -y typing
|
||||
pip install -r requirements_test_all.txt
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
pip install -e .
|
||||
@@ -209,11 +206,8 @@ stages:
|
||||
|
||||
. venv/bin/activate
|
||||
pip install -U pip setuptools wheel
|
||||
pip install -r requirements_all.txt -c homeassistant/package_constraints.txt
|
||||
pip install -r requirements_test.txt -c homeassistant/package_constraints.txt
|
||||
# This is a TEMP. Eventually we should make sure our 4 dependencies drop typing.
|
||||
# Find offending deps with `pipdeptree -r -p typing`
|
||||
pip uninstall -y typing
|
||||
pip install -r requirements_all.txt
|
||||
pip install -r requirements_test.txt
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
pip install -e .
|
||||
@@ -234,7 +228,7 @@ stages:
|
||||
python -m venv venv
|
||||
|
||||
. venv/bin/activate
|
||||
pip install -e . -r requirements_test.txt -c homeassistant/package_constraints.txt
|
||||
pip install -e . -r requirements_test.txt
|
||||
pre-commit install-hooks
|
||||
- script: |
|
||||
. venv/bin/activate
|
||||
|
@@ -17,7 +17,7 @@ schedules:
|
||||
- dev
|
||||
variables:
|
||||
- name: versionWheels
|
||||
value: '1.10.1-3.7-alpine3.11'
|
||||
value: '1.13.0-3.8-alpine3.12'
|
||||
resources:
|
||||
repositories:
|
||||
- repository: azure
|
||||
@@ -29,12 +29,32 @@ jobs:
|
||||
- template: templates/azp-job-wheels.yaml@azure
|
||||
parameters:
|
||||
builderVersion: '$(versionWheels)'
|
||||
builderApk: 'build-base;cmake;git;linux-headers;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;autoconf;automake;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev'
|
||||
builderApk: 'build-base;cmake;git;linux-headers;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev'
|
||||
builderPip: 'Cython;numpy'
|
||||
skipBinary: 'aiohttp'
|
||||
wheelsRequirement: 'requirements.txt'
|
||||
wheelsRequirementDiff: 'requirements_diff.txt'
|
||||
wheelsConstraint: 'homeassistant/package_constraints.txt'
|
||||
jobName: 'Wheels_Core'
|
||||
preBuild:
|
||||
- script: |
|
||||
if [[ "$(Build.Reason)" =~ (Schedule|Manual) ]]; then
|
||||
exit 0
|
||||
else
|
||||
curl -s -o requirements_diff.txt https://raw.githubusercontent.com/home-assistant/core/master/requirements.txt
|
||||
fi
|
||||
displayName: 'Prepare requirements files for Home Assistant Core wheels'
|
||||
- template: templates/azp-job-wheels.yaml@azure
|
||||
parameters:
|
||||
builderVersion: '$(versionWheels)'
|
||||
builderApk: 'build-base;cmake;git;linux-headers;libexecinfo-dev;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;autoconf;automake;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev'
|
||||
builderPip: 'Cython;numpy;scikit-build'
|
||||
builderEnvFile: true
|
||||
skipBinary: 'aiohttp'
|
||||
wheelsRequirement: 'requirements_wheels.txt'
|
||||
wheelsRequirementDiff: 'requirements_diff.txt'
|
||||
wheelsConstraint: 'homeassistant/package_constraints.txt'
|
||||
jobName: 'Wheels_Integrations'
|
||||
preBuild:
|
||||
- script: |
|
||||
cp requirements_all.txt requirements_wheels.txt
|
||||
@@ -71,4 +91,10 @@ jobs:
|
||||
sed -i "s|# bme680|bme680|g" ${requirement_file}
|
||||
sed -i "s|# python-gammu|python-gammu|g" ${requirement_file}
|
||||
done
|
||||
|
||||
# Write env for build settings
|
||||
(
|
||||
echo "GRPC_BUILD_WITH_BORING_SSL_ASM="
|
||||
echo "GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1"
|
||||
) > .env_file
|
||||
displayName: 'Prepare requirements files for Home Assistant wheels'
|
||||
|
10
build.json
10
build.json
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"image": "homeassistant/{arch}-homeassistant",
|
||||
"build_from": {
|
||||
"aarch64": "homeassistant/aarch64-homeassistant-base:7.2.0",
|
||||
"armhf": "homeassistant/armhf-homeassistant-base:7.2.0",
|
||||
"armv7": "homeassistant/armv7-homeassistant-base:7.2.0",
|
||||
"amd64": "homeassistant/amd64-homeassistant-base:7.2.0",
|
||||
"i386": "homeassistant/i386-homeassistant-base:7.2.0"
|
||||
"aarch64": "homeassistant/aarch64-homeassistant-base:8.4.0",
|
||||
"armhf": "homeassistant/armhf-homeassistant-base:8.4.0",
|
||||
"armv7": "homeassistant/armv7-homeassistant-base:8.4.0",
|
||||
"amd64": "homeassistant/amd64-homeassistant-base:8.4.0",
|
||||
"i386": "homeassistant/i386-homeassistant-base:8.4.0"
|
||||
},
|
||||
"labels": {
|
||||
"io.hass.type": "core"
|
||||
|
@@ -1,6 +1,5 @@
|
||||
"""Start Home Assistant."""
|
||||
import argparse
|
||||
import asyncio
|
||||
import os
|
||||
import platform
|
||||
import subprocess
|
||||
@@ -8,32 +7,9 @@ import sys
|
||||
import threading
|
||||
from typing import List
|
||||
|
||||
import yarl
|
||||
|
||||
from homeassistant.const import REQUIRED_PYTHON_VER, RESTART_EXIT_CODE, __version__
|
||||
|
||||
|
||||
def set_loop() -> None:
|
||||
"""Attempt to use different loop."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from asyncio.events import BaseDefaultEventLoopPolicy
|
||||
|
||||
if sys.platform == "win32":
|
||||
if hasattr(asyncio, "WindowsProactorEventLoopPolicy"):
|
||||
# pylint: disable=no-member
|
||||
policy = asyncio.WindowsProactorEventLoopPolicy()
|
||||
else:
|
||||
|
||||
class ProactorPolicy(BaseDefaultEventLoopPolicy):
|
||||
"""Event loop policy to create proactor loops."""
|
||||
|
||||
_loop_factory = asyncio.ProactorEventLoop
|
||||
|
||||
policy = ProactorPolicy()
|
||||
|
||||
asyncio.set_event_loop_policy(policy)
|
||||
|
||||
|
||||
def validate_python() -> None:
|
||||
"""Validate that the right Python version is running."""
|
||||
if sys.version_info[:3] < REQUIRED_PYTHON_VER:
|
||||
@@ -219,7 +195,7 @@ def closefds_osx(min_fd: int, max_fd: int) -> None:
|
||||
get rid of.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from fcntl import fcntl, F_GETFD, F_SETFD, FD_CLOEXEC
|
||||
from fcntl import F_GETFD, F_SETFD, FD_CLOEXEC, fcntl
|
||||
|
||||
for _fd in range(min_fd, max_fd):
|
||||
try:
|
||||
@@ -240,39 +216,6 @@ def cmdline() -> List[str]:
|
||||
return [arg for arg in sys.argv if arg != "--daemon"]
|
||||
|
||||
|
||||
async def setup_and_run_hass(config_dir: str, args: argparse.Namespace) -> int:
|
||||
"""Set up Home Assistant and run."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from homeassistant import bootstrap
|
||||
|
||||
hass = await bootstrap.async_setup_hass(
|
||||
config_dir=config_dir,
|
||||
verbose=args.verbose,
|
||||
log_rotate_days=args.log_rotate_days,
|
||||
log_file=args.log_file,
|
||||
log_no_color=args.log_no_color,
|
||||
skip_pip=args.skip_pip,
|
||||
safe_mode=args.safe_mode,
|
||||
)
|
||||
|
||||
if hass is None:
|
||||
return 1
|
||||
|
||||
if args.open_ui:
|
||||
import webbrowser # pylint: disable=import-outside-toplevel
|
||||
|
||||
if hass.config.api is not None:
|
||||
scheme = "https" if hass.config.api.use_ssl else "http"
|
||||
url = str(
|
||||
yarl.URL.build(
|
||||
scheme=scheme, host="127.0.0.1", port=hass.config.api.port
|
||||
)
|
||||
)
|
||||
hass.add_job(webbrowser.open, url)
|
||||
|
||||
return await hass.async_run()
|
||||
|
||||
|
||||
def try_to_restart() -> None:
|
||||
"""Attempt to clean up state and start a new Home Assistant instance."""
|
||||
# Things should be mostly shut down already at this point, now just try
|
||||
@@ -319,8 +262,6 @@ def main() -> int:
|
||||
"""Start Home Assistant."""
|
||||
validate_python()
|
||||
|
||||
set_loop()
|
||||
|
||||
# Run a simple daemon runner process on Windows to handle restarts
|
||||
if os.name == "nt" and "--runner" not in sys.argv:
|
||||
nt_args = cmdline() + ["--runner"]
|
||||
@@ -353,7 +294,22 @@ def main() -> int:
|
||||
if args.pid_file:
|
||||
write_pid(args.pid_file)
|
||||
|
||||
exit_code = asyncio.run(setup_and_run_hass(config_dir, args), debug=args.debug)
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from homeassistant import runner
|
||||
|
||||
runtime_conf = runner.RuntimeConfig(
|
||||
config_dir=config_dir,
|
||||
verbose=args.verbose,
|
||||
log_rotate_days=args.log_rotate_days,
|
||||
log_file=args.log_file,
|
||||
log_no_color=args.log_no_color,
|
||||
skip_pip=args.skip_pip,
|
||||
safe_mode=args.safe_mode,
|
||||
debug=args.debug,
|
||||
open_ui=args.open_ui,
|
||||
)
|
||||
|
||||
exit_code = runner.run(runtime_conf)
|
||||
if exit_code == RESTART_EXIT_CODE and not args.runner:
|
||||
try_to_restart()
|
||||
|
||||
|
@@ -312,9 +312,7 @@ class AuthManager:
|
||||
|
||||
if provider is not None and hasattr(provider, "async_will_remove_credentials"):
|
||||
# https://github.com/python/mypy/issues/1424
|
||||
await provider.async_will_remove_credentials( # type: ignore
|
||||
credentials
|
||||
)
|
||||
await provider.async_will_remove_credentials(credentials) # type: ignore
|
||||
|
||||
await self._store.async_remove_credentials(credentials)
|
||||
|
||||
|
@@ -150,7 +150,9 @@ async def _load_mfa_module(hass: HomeAssistant, module_name: str) -> types.Modul
|
||||
module = importlib.import_module(module_path)
|
||||
except ImportError as err:
|
||||
_LOGGER.error("Unable to load mfa module %s: %s", module_name, err)
|
||||
raise HomeAssistantError(f"Unable to load mfa module {module_name}: {err}")
|
||||
raise HomeAssistantError(
|
||||
f"Unable to load mfa module {module_name}: {err}"
|
||||
) from err
|
||||
|
||||
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
|
||||
return module
|
||||
|
@@ -77,10 +77,10 @@ def _verify_otp(secret: str, otp: str, count: int) -> bool:
|
||||
class NotifySetting:
|
||||
"""Store notify setting for one user."""
|
||||
|
||||
secret = attr.ib(type=str, factory=_generate_secret) # not persistent
|
||||
counter = attr.ib(type=int, factory=_generate_random) # not persistent
|
||||
notify_service = attr.ib(type=Optional[str], default=None)
|
||||
target = attr.ib(type=Optional[str], default=None)
|
||||
secret: str = attr.ib(factory=_generate_secret) # not persistent
|
||||
counter: int = attr.ib(factory=_generate_random) # not persistent
|
||||
notify_service: Optional[str] = attr.ib(default=None)
|
||||
target: Optional[str] = attr.ib(default=None)
|
||||
|
||||
|
||||
_UsersDict = Dict[str, NotifySetting]
|
||||
|
@@ -20,35 +20,34 @@ TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = "long_lived_access_token"
|
||||
class Group:
|
||||
"""A group."""
|
||||
|
||||
name = attr.ib(type=Optional[str])
|
||||
policy = attr.ib(type=perm_mdl.PolicyType)
|
||||
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
||||
system_generated = attr.ib(type=bool, default=False)
|
||||
name: Optional[str] = attr.ib()
|
||||
policy: perm_mdl.PolicyType = attr.ib()
|
||||
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
|
||||
system_generated: bool = attr.ib(default=False)
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
class User:
|
||||
"""A user."""
|
||||
|
||||
name = attr.ib(type=Optional[str])
|
||||
perm_lookup = attr.ib(type=perm_mdl.PermissionLookup, eq=False, order=False)
|
||||
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
||||
is_owner = attr.ib(type=bool, default=False)
|
||||
is_active = attr.ib(type=bool, default=False)
|
||||
system_generated = attr.ib(type=bool, default=False)
|
||||
name: Optional[str] = attr.ib()
|
||||
perm_lookup: perm_mdl.PermissionLookup = attr.ib(eq=False, order=False)
|
||||
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
|
||||
is_owner: bool = attr.ib(default=False)
|
||||
is_active: bool = attr.ib(default=False)
|
||||
system_generated: bool = attr.ib(default=False)
|
||||
|
||||
groups = attr.ib(type=List[Group], factory=list, eq=False, order=False)
|
||||
groups: List[Group] = attr.ib(factory=list, eq=False, order=False)
|
||||
|
||||
# List of credentials of a user.
|
||||
credentials = attr.ib(type=List["Credentials"], factory=list, eq=False, order=False)
|
||||
credentials: List["Credentials"] = attr.ib(factory=list, eq=False, order=False)
|
||||
|
||||
# Tokens associated with a user.
|
||||
refresh_tokens = attr.ib(
|
||||
type=Dict[str, "RefreshToken"], factory=dict, eq=False, order=False
|
||||
refresh_tokens: Dict[str, "RefreshToken"] = attr.ib(
|
||||
factory=dict, eq=False, order=False
|
||||
)
|
||||
|
||||
_permissions = attr.ib(
|
||||
type=Optional[perm_mdl.PolicyPermissions],
|
||||
_permissions: Optional[perm_mdl.PolicyPermissions] = attr.ib(
|
||||
init=False,
|
||||
eq=False,
|
||||
order=False,
|
||||
@@ -88,39 +87,38 @@ class User:
|
||||
class RefreshToken:
|
||||
"""RefreshToken for a user to grant new access tokens."""
|
||||
|
||||
user = attr.ib(type=User)
|
||||
client_id = attr.ib(type=Optional[str])
|
||||
access_token_expiration = attr.ib(type=timedelta)
|
||||
client_name = attr.ib(type=Optional[str], default=None)
|
||||
client_icon = attr.ib(type=Optional[str], default=None)
|
||||
token_type = attr.ib(
|
||||
type=str,
|
||||
user: User = attr.ib()
|
||||
client_id: Optional[str] = attr.ib()
|
||||
access_token_expiration: timedelta = attr.ib()
|
||||
client_name: Optional[str] = attr.ib(default=None)
|
||||
client_icon: Optional[str] = attr.ib(default=None)
|
||||
token_type: str = attr.ib(
|
||||
default=TOKEN_TYPE_NORMAL,
|
||||
validator=attr.validators.in_(
|
||||
(TOKEN_TYPE_NORMAL, TOKEN_TYPE_SYSTEM, TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN)
|
||||
),
|
||||
)
|
||||
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
||||
created_at = attr.ib(type=datetime, factory=dt_util.utcnow)
|
||||
token = attr.ib(type=str, factory=lambda: secrets.token_hex(64))
|
||||
jwt_key = attr.ib(type=str, factory=lambda: secrets.token_hex(64))
|
||||
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
|
||||
created_at: datetime = attr.ib(factory=dt_util.utcnow)
|
||||
token: str = attr.ib(factory=lambda: secrets.token_hex(64))
|
||||
jwt_key: str = attr.ib(factory=lambda: secrets.token_hex(64))
|
||||
|
||||
last_used_at = attr.ib(type=Optional[datetime], default=None)
|
||||
last_used_ip = attr.ib(type=Optional[str], default=None)
|
||||
last_used_at: Optional[datetime] = attr.ib(default=None)
|
||||
last_used_ip: Optional[str] = attr.ib(default=None)
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
class Credentials:
|
||||
"""Credentials for a user on an auth provider."""
|
||||
|
||||
auth_provider_type = attr.ib(type=str)
|
||||
auth_provider_id = attr.ib(type=Optional[str])
|
||||
auth_provider_type: str = attr.ib()
|
||||
auth_provider_id: Optional[str] = attr.ib()
|
||||
|
||||
# Allow the auth provider to store data to represent their auth.
|
||||
data = attr.ib(type=dict)
|
||||
data: dict = attr.ib()
|
||||
|
||||
id = attr.ib(type=str, factory=lambda: uuid.uuid4().hex)
|
||||
is_new = attr.ib(type=bool, default=True)
|
||||
id: str = attr.ib(factory=lambda: uuid.uuid4().hex)
|
||||
is_new: bool = attr.ib(default=True)
|
||||
|
||||
|
||||
class UserMeta(NamedTuple):
|
||||
|
@@ -72,4 +72,4 @@ class _OwnerPermissions(AbstractPermissions):
|
||||
return lambda entity_id, key: True
|
||||
|
||||
|
||||
OwnerPermissions = _OwnerPermissions() # pylint: disable=invalid-name
|
||||
OwnerPermissions = _OwnerPermissions()
|
||||
|
@@ -5,13 +5,15 @@ import attr
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# pylint: disable=unused-import
|
||||
from homeassistant.helpers import entity_registry as ent_reg # noqa: F401
|
||||
from homeassistant.helpers import device_registry as dev_reg # noqa: F401
|
||||
from homeassistant.helpers import ( # noqa: F401
|
||||
device_registry as dev_reg,
|
||||
entity_registry as ent_reg,
|
||||
)
|
||||
|
||||
|
||||
@attr.s(slots=True)
|
||||
class PermissionLookup:
|
||||
"""Class to hold data for permission lookups."""
|
||||
|
||||
entity_registry = attr.ib(type="ent_reg.EntityRegistry")
|
||||
device_registry = attr.ib(type="dev_reg.DeviceRegistry")
|
||||
entity_registry: "ent_reg.EntityRegistry" = attr.ib()
|
||||
device_registry: "dev_reg.DeviceRegistry" = attr.ib()
|
||||
|
@@ -146,7 +146,9 @@ async def load_auth_provider_module(
|
||||
module = importlib.import_module(f"homeassistant.auth.providers.{provider}")
|
||||
except ImportError as err:
|
||||
_LOGGER.error("Unable to load auth provider %s: %s", provider, err)
|
||||
raise HomeAssistantError(f"Unable to load auth provider {provider}: {err}")
|
||||
raise HomeAssistantError(
|
||||
f"Unable to load auth provider {provider}: {err}"
|
||||
) from err
|
||||
|
||||
if hass.config.skip_pip or not hasattr(module, "REQUIREMENTS"):
|
||||
return module
|
||||
|
@@ -71,11 +71,11 @@ class CommandLineAuthProvider(AuthProvider):
|
||||
except OSError as err:
|
||||
# happens when command doesn't exist or permission is denied
|
||||
_LOGGER.error("Error while authenticating %r: %s", username, err)
|
||||
raise InvalidAuthError
|
||||
raise InvalidAuthError from err
|
||||
|
||||
if process.returncode != 0:
|
||||
_LOGGER.error(
|
||||
"User %r failed to authenticate, command exited with code %d.",
|
||||
"User %r failed to authenticate, command exited with code %d",
|
||||
username,
|
||||
process.returncode,
|
||||
)
|
||||
|
@@ -30,6 +30,16 @@ def _disallow_id(conf: Dict[str, Any]) -> Dict[str, Any]:
|
||||
CONFIG_SCHEMA = vol.All(AUTH_PROVIDER_SCHEMA, _disallow_id)
|
||||
|
||||
|
||||
@callback
|
||||
def async_get_provider(hass: HomeAssistant) -> "HassAuthProvider":
|
||||
"""Get the provider."""
|
||||
for prv in hass.auth.auth_providers:
|
||||
if prv.type == "homeassistant":
|
||||
return cast(HassAuthProvider, prv)
|
||||
|
||||
raise RuntimeError("Provider not found")
|
||||
|
||||
|
||||
class InvalidAuth(HomeAssistantError):
|
||||
"""Raised when we encounter invalid authentication."""
|
||||
|
||||
@@ -235,6 +245,35 @@ class HassAuthProvider(AuthProvider):
|
||||
self.data.validate_login, username, password
|
||||
)
|
||||
|
||||
async def async_add_auth(self, username: str, password: str) -> None:
|
||||
"""Call add_auth on data."""
|
||||
if self.data is None:
|
||||
await self.async_initialize()
|
||||
assert self.data is not None
|
||||
|
||||
await self.hass.async_add_executor_job(self.data.add_auth, username, password)
|
||||
await self.data.async_save()
|
||||
|
||||
async def async_remove_auth(self, username: str) -> None:
|
||||
"""Call remove_auth on data."""
|
||||
if self.data is None:
|
||||
await self.async_initialize()
|
||||
assert self.data is not None
|
||||
|
||||
self.data.async_remove_auth(username)
|
||||
await self.data.async_save()
|
||||
|
||||
async def async_change_password(self, username: str, new_password: str) -> None:
|
||||
"""Call change_password on data."""
|
||||
if self.data is None:
|
||||
await self.async_initialize()
|
||||
assert self.data is not None
|
||||
|
||||
await self.hass.async_add_executor_job(
|
||||
self.data.change_password, username, new_password
|
||||
)
|
||||
await self.data.async_save()
|
||||
|
||||
async def async_get_or_create_credentials(
|
||||
self, flow_result: Dict[str, str]
|
||||
) -> Credentials:
|
||||
|
@@ -190,7 +190,7 @@ class TrustedNetworksLoginFlow(LoginFlow):
|
||||
).async_validate_access(self._ip_address)
|
||||
|
||||
except InvalidAuthError:
|
||||
return self.async_abort(reason="not_whitelisted")
|
||||
return self.async_abort(reason="not_allowed")
|
||||
|
||||
if user_input is not None:
|
||||
return await self.async_finish(user_input)
|
||||
|
@@ -7,7 +7,7 @@ from homeassistant.util.async_ import protect_loop
|
||||
def enable() -> None:
|
||||
"""Enable the detection of I/O in the event loop."""
|
||||
# Prevent urllib3 and requests doing I/O in event loop
|
||||
HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest)
|
||||
HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest) # type: ignore
|
||||
|
||||
# Currently disabled. pytz doing I/O when getting timezone.
|
||||
# Prevent files being opened inside the event loop
|
||||
|
@@ -6,11 +6,12 @@ import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
from time import monotonic
|
||||
from typing import Any, Dict, Optional, Set
|
||||
from typing import TYPE_CHECKING, Any, Dict, Optional, Set
|
||||
|
||||
from async_timeout import timeout
|
||||
import voluptuous as vol
|
||||
import yarl
|
||||
|
||||
from homeassistant import config as conf_util, config_entries, core, loader
|
||||
from homeassistant.components import http
|
||||
@@ -31,6 +32,9 @@ from homeassistant.util.logging import async_activate_log_queue_handler
|
||||
from homeassistant.util.package import async_get_user_site, is_virtual_env
|
||||
from homeassistant.util.yaml import clear_secret_cache
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .runner import RuntimeConfig
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ERROR_LOG_FILENAME = "home-assistant.log"
|
||||
@@ -40,6 +44,11 @@ DATA_LOGGING = "logging"
|
||||
|
||||
LOG_SLOW_STARTUP_INTERVAL = 60
|
||||
|
||||
STAGE_1_TIMEOUT = 120
|
||||
STAGE_2_TIMEOUT = 300
|
||||
WRAP_UP_TIMEOUT = 300
|
||||
COOLDOWN_TIME = 60
|
||||
|
||||
DEBUGGER_INTEGRATIONS = {"debugpy", "ptvsd"}
|
||||
CORE_INTEGRATIONS = ("homeassistant", "persistent_notification")
|
||||
LOGGING_INTEGRATIONS = {
|
||||
@@ -66,23 +75,22 @@ STAGE_1_INTEGRATIONS = {
|
||||
|
||||
|
||||
async def async_setup_hass(
|
||||
*,
|
||||
config_dir: str,
|
||||
verbose: bool,
|
||||
log_rotate_days: int,
|
||||
log_file: str,
|
||||
log_no_color: bool,
|
||||
skip_pip: bool,
|
||||
safe_mode: bool,
|
||||
runtime_config: "RuntimeConfig",
|
||||
) -> Optional[core.HomeAssistant]:
|
||||
"""Set up Home Assistant."""
|
||||
hass = core.HomeAssistant()
|
||||
hass.config.config_dir = config_dir
|
||||
hass.config.config_dir = runtime_config.config_dir
|
||||
|
||||
async_enable_logging(hass, verbose, log_rotate_days, log_file, log_no_color)
|
||||
async_enable_logging(
|
||||
hass,
|
||||
runtime_config.verbose,
|
||||
runtime_config.log_rotate_days,
|
||||
runtime_config.log_file,
|
||||
runtime_config.log_no_color,
|
||||
)
|
||||
|
||||
hass.config.skip_pip = skip_pip
|
||||
if skip_pip:
|
||||
hass.config.skip_pip = runtime_config.skip_pip
|
||||
if runtime_config.skip_pip:
|
||||
_LOGGER.warning(
|
||||
"Skipping pip installation of required modules. This may cause issues"
|
||||
)
|
||||
@@ -91,10 +99,11 @@ async def async_setup_hass(
|
||||
_LOGGER.error("Error getting configuration path")
|
||||
return None
|
||||
|
||||
_LOGGER.info("Config directory: %s", config_dir)
|
||||
_LOGGER.info("Config directory: %s", runtime_config.config_dir)
|
||||
|
||||
config_dict = None
|
||||
basic_setup_success = False
|
||||
safe_mode = runtime_config.safe_mode
|
||||
|
||||
if not safe_mode:
|
||||
await hass.async_add_executor_job(conf_util.process_ha_config_upgrade, hass)
|
||||
@@ -103,11 +112,12 @@ async def async_setup_hass(
|
||||
config_dict = await conf_util.async_hass_config_yaml(hass)
|
||||
except HomeAssistantError as err:
|
||||
_LOGGER.error(
|
||||
"Failed to parse configuration.yaml: %s. Activating safe mode", err,
|
||||
"Failed to parse configuration.yaml: %s. Activating safe mode",
|
||||
err,
|
||||
)
|
||||
else:
|
||||
if not is_virtual_env():
|
||||
await async_mount_local_lib_path(config_dir)
|
||||
await async_mount_local_lib_path(runtime_config.config_dir)
|
||||
|
||||
basic_setup_success = (
|
||||
await async_from_config_dict(config_dict, hass) is not None
|
||||
@@ -132,11 +142,12 @@ async def async_setup_hass(
|
||||
hass.async_track_tasks()
|
||||
hass.bus.async_fire(EVENT_HOMEASSISTANT_STOP, {})
|
||||
with contextlib.suppress(asyncio.TimeoutError):
|
||||
async with timeout(10):
|
||||
async with hass.timeout.async_timeout(10):
|
||||
await hass.async_block_till_done()
|
||||
|
||||
safe_mode = True
|
||||
old_config = hass.config
|
||||
|
||||
hass = core.HomeAssistant()
|
||||
hass.config.skip_pip = old_config.skip_pip
|
||||
hass.config.internal_url = old_config.internal_url
|
||||
@@ -150,12 +161,36 @@ async def async_setup_hass(
|
||||
http_conf = (await http.async_get_last_config(hass)) or {}
|
||||
|
||||
await async_from_config_dict(
|
||||
{"safe_mode": {}, "http": http_conf}, hass,
|
||||
{"safe_mode": {}, "http": http_conf},
|
||||
hass,
|
||||
)
|
||||
|
||||
if runtime_config.open_ui:
|
||||
hass.add_job(open_hass_ui, hass)
|
||||
|
||||
return hass
|
||||
|
||||
|
||||
def open_hass_ui(hass: core.HomeAssistant) -> None:
|
||||
"""Open the UI."""
|
||||
import webbrowser # pylint: disable=import-outside-toplevel
|
||||
|
||||
if hass.config.api is None or "frontend" not in hass.config.components:
|
||||
_LOGGER.warning("Cannot launch the UI because frontend not loaded")
|
||||
return
|
||||
|
||||
scheme = "https" if hass.config.api.use_ssl else "http"
|
||||
url = str(
|
||||
yarl.URL.build(scheme=scheme, host="127.0.0.1", port=hass.config.api.port)
|
||||
)
|
||||
|
||||
if not webbrowser.open(url):
|
||||
_LOGGER.warning(
|
||||
"Unable to open the Home Assistant UI in a browser. Open it yourself at %s",
|
||||
url,
|
||||
)
|
||||
|
||||
|
||||
async def async_from_config_dict(
|
||||
config: ConfigType, hass: core.HomeAssistant
|
||||
) -> Optional[core.HomeAssistant]:
|
||||
@@ -276,6 +311,12 @@ def async_enable_logging(
|
||||
"Uncaught exception", exc_info=args # type: ignore
|
||||
)
|
||||
|
||||
if sys.version_info[:2] >= (3, 8):
|
||||
threading.excepthook = lambda args: logging.getLogger(None).exception(
|
||||
"Uncaught thread exception",
|
||||
exc_info=(args.exc_type, args.exc_value, args.exc_traceback),
|
||||
)
|
||||
|
||||
# Log errors to a file if we have write access to file or config dir
|
||||
if log_file is None:
|
||||
err_log_path = hass.config.path(ERROR_LOG_FILENAME)
|
||||
@@ -292,8 +333,10 @@ def async_enable_logging(
|
||||
):
|
||||
|
||||
if log_rotate_days:
|
||||
err_handler: logging.FileHandler = logging.handlers.TimedRotatingFileHandler(
|
||||
err_log_path, when="midnight", backupCount=log_rotate_days
|
||||
err_handler: logging.FileHandler = (
|
||||
logging.handlers.TimedRotatingFileHandler(
|
||||
err_log_path, when="midnight", backupCount=log_rotate_days
|
||||
)
|
||||
)
|
||||
else:
|
||||
err_handler = logging.FileHandler(err_log_path, mode="w", delay=True)
|
||||
@@ -351,8 +394,9 @@ async def _async_log_pending_setups(
|
||||
remaining = [domain for domain in domains if domain in setup_started]
|
||||
|
||||
if remaining:
|
||||
_LOGGER.info(
|
||||
"Waiting on integrations to complete setup: %s", ", ".join(remaining),
|
||||
_LOGGER.warning(
|
||||
"Waiting on integrations to complete setup: %s",
|
||||
", ".join(remaining),
|
||||
)
|
||||
|
||||
|
||||
@@ -468,24 +512,42 @@ async def _async_set_up_integrations(
|
||||
stage_2_domains = domains_to_setup - logging_domains - debuggers - stage_1_domains
|
||||
|
||||
# Kick off loading the registries. They don't need to be awaited.
|
||||
asyncio.gather(
|
||||
hass.helpers.device_registry.async_get_registry(),
|
||||
hass.helpers.entity_registry.async_get_registry(),
|
||||
hass.helpers.area_registry.async_get_registry(),
|
||||
)
|
||||
asyncio.create_task(hass.helpers.device_registry.async_get_registry())
|
||||
asyncio.create_task(hass.helpers.entity_registry.async_get_registry())
|
||||
asyncio.create_task(hass.helpers.area_registry.async_get_registry())
|
||||
|
||||
# Start setup
|
||||
if stage_1_domains:
|
||||
_LOGGER.info("Setting up stage 1: %s", stage_1_domains)
|
||||
await async_setup_multi_components(hass, stage_1_domains, config, setup_started)
|
||||
try:
|
||||
async with hass.timeout.async_timeout(
|
||||
STAGE_1_TIMEOUT, cool_down=COOLDOWN_TIME
|
||||
):
|
||||
await async_setup_multi_components(
|
||||
hass, stage_1_domains, config, setup_started
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.warning("Setup timed out for stage 1 - moving forward")
|
||||
|
||||
# Enables after dependencies
|
||||
async_set_domains_to_be_loaded(hass, stage_1_domains | stage_2_domains)
|
||||
|
||||
if stage_2_domains:
|
||||
_LOGGER.info("Setting up stage 2: %s", stage_2_domains)
|
||||
await async_setup_multi_components(hass, stage_2_domains, config, setup_started)
|
||||
try:
|
||||
async with hass.timeout.async_timeout(
|
||||
STAGE_2_TIMEOUT, cool_down=COOLDOWN_TIME
|
||||
):
|
||||
await async_setup_multi_components(
|
||||
hass, stage_2_domains, config, setup_started
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.warning("Setup timed out for stage 2 - moving forward")
|
||||
|
||||
# Wrap up startup
|
||||
_LOGGER.debug("Waiting for startup to wrap up")
|
||||
await hass.async_block_till_done()
|
||||
try:
|
||||
async with hass.timeout.async_timeout(WRAP_UP_TIMEOUT, cool_down=COOLDOWN_TIME):
|
||||
await hass.async_block_till_done()
|
||||
except asyncio.TimeoutError:
|
||||
_LOGGER.warning("Setup timed out for bootstrap - moving forward")
|
||||
|
@@ -37,7 +37,7 @@ def is_on(hass, entity_id=None):
|
||||
continue
|
||||
|
||||
if not hasattr(component, "is_on"):
|
||||
_LOGGER.warning("Integration %s has no is_on method.", domain)
|
||||
_LOGGER.warning("Integration %s has no is_on method", domain)
|
||||
continue
|
||||
|
||||
if component.is_on(ent_id):
|
||||
|
@@ -120,7 +120,7 @@ async def async_setup_entry(hass, config_entry):
|
||||
|
||||
except (AbodeException, ConnectTimeout, HTTPError) as ex:
|
||||
LOGGER.error("Unable to connect to Abode: %s", str(ex))
|
||||
raise ConfigEntryNotReady
|
||||
raise ConfigEntryNotReady from ex
|
||||
|
||||
for platform in ABODE_PLATFORMS:
|
||||
hass.async_create_task(
|
||||
@@ -261,6 +261,7 @@ def setup_abode_events(hass):
|
||||
TIMELINE.AUTOMATION_GROUP,
|
||||
TIMELINE.DISARM_GROUP,
|
||||
TIMELINE.ARM_GROUP,
|
||||
TIMELINE.ARM_FAULT_GROUP,
|
||||
TIMELINE.TEST_GROUP,
|
||||
TIMELINE.CAPTURE_GROUP,
|
||||
TIMELINE.DEVICE_GROUP,
|
||||
|
@@ -82,8 +82,21 @@ class AbodeCamera(AbodeDevice, Camera):
|
||||
|
||||
return None
|
||||
|
||||
def turn_on(self):
|
||||
"""Turn on camera."""
|
||||
self._device.privacy_mode(False)
|
||||
|
||||
def turn_off(self):
|
||||
"""Turn off camera."""
|
||||
self._device.privacy_mode(True)
|
||||
|
||||
def _capture_callback(self, capture):
|
||||
"""Update the image with the device then refresh device."""
|
||||
self._device.update_image_location(capture)
|
||||
self.get_image()
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if on."""
|
||||
return self._device.is_on
|
||||
|
@@ -3,7 +3,7 @@
|
||||
"name": "Abode",
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/abode",
|
||||
"requirements": ["abodepy==0.19.0"],
|
||||
"requirements": ["abodepy==1.1.0"],
|
||||
"codeowners": ["@shred86"],
|
||||
"homekit": {
|
||||
"models": ["Abode", "Iota"]
|
||||
|
132
homeassistant/components/accuweather/__init__.py
Normal file
132
homeassistant/components/accuweather/__init__.py
Normal file
@@ -0,0 +1,132 @@
|
||||
"""The AccuWeather component."""
|
||||
import asyncio
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from accuweather import AccuWeather, ApiError, InvalidApiKeyError, RequestsExceededError
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from async_timeout import timeout
|
||||
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.core import Config, HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
from .const import (
|
||||
ATTR_FORECAST,
|
||||
CONF_FORECAST,
|
||||
COORDINATOR,
|
||||
DOMAIN,
|
||||
UNDO_UPDATE_LISTENER,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
PLATFORMS = ["sensor", "weather"]
|
||||
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: Config) -> bool:
|
||||
"""Set up configured AccuWeather."""
|
||||
hass.data.setdefault(DOMAIN, {})
|
||||
return True
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry) -> bool:
|
||||
"""Set up AccuWeather as config entry."""
|
||||
api_key = config_entry.data[CONF_API_KEY]
|
||||
location_key = config_entry.unique_id
|
||||
forecast = config_entry.options.get(CONF_FORECAST, False)
|
||||
|
||||
_LOGGER.debug("Using location_key: %s, get forecast: %s", location_key, forecast)
|
||||
|
||||
websession = async_get_clientsession(hass)
|
||||
|
||||
coordinator = AccuWeatherDataUpdateCoordinator(
|
||||
hass, websession, api_key, location_key, forecast
|
||||
)
|
||||
await coordinator.async_refresh()
|
||||
|
||||
if not coordinator.last_update_success:
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
undo_listener = config_entry.add_update_listener(update_listener)
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id] = {
|
||||
COORDINATOR: coordinator,
|
||||
UNDO_UPDATE_LISTENER: undo_listener,
|
||||
}
|
||||
|
||||
for component in PLATFORMS:
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(config_entry, component)
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass, config_entry):
|
||||
"""Unload a config entry."""
|
||||
unload_ok = all(
|
||||
await asyncio.gather(
|
||||
*[
|
||||
hass.config_entries.async_forward_entry_unload(config_entry, component)
|
||||
for component in PLATFORMS
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
hass.data[DOMAIN][config_entry.entry_id][UNDO_UPDATE_LISTENER]()
|
||||
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(config_entry.entry_id)
|
||||
|
||||
return unload_ok
|
||||
|
||||
|
||||
async def update_listener(hass, config_entry):
|
||||
"""Update listener."""
|
||||
await hass.config_entries.async_reload(config_entry.entry_id)
|
||||
|
||||
|
||||
class AccuWeatherDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
"""Class to manage fetching AccuWeather data API."""
|
||||
|
||||
def __init__(self, hass, session, api_key, location_key, forecast: bool):
|
||||
"""Initialize."""
|
||||
self.location_key = location_key
|
||||
self.forecast = forecast
|
||||
self.is_metric = hass.config.units.is_metric
|
||||
self.accuweather = AccuWeather(api_key, session, location_key=self.location_key)
|
||||
|
||||
# Enabling the forecast download increases the number of requests per data
|
||||
# update, we use 32 minutes for current condition only and 64 minutes for
|
||||
# current condition and forecast as update interval to not exceed allowed number
|
||||
# of requests. We have 50 requests allowed per day, so we use 45 and leave 5 as
|
||||
# a reserve for restarting HA.
|
||||
update_interval = (
|
||||
timedelta(minutes=64) if self.forecast else timedelta(minutes=32)
|
||||
)
|
||||
_LOGGER.debug("Data will be update every %s", update_interval)
|
||||
|
||||
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=update_interval)
|
||||
|
||||
async def _async_update_data(self):
|
||||
"""Update data via library."""
|
||||
try:
|
||||
async with timeout(10):
|
||||
current = await self.accuweather.async_get_current_conditions()
|
||||
forecast = (
|
||||
await self.accuweather.async_get_forecast(metric=self.is_metric)
|
||||
if self.forecast
|
||||
else {}
|
||||
)
|
||||
except (
|
||||
ApiError,
|
||||
ClientConnectorError,
|
||||
InvalidApiKeyError,
|
||||
RequestsExceededError,
|
||||
) as error:
|
||||
raise UpdateFailed(error) from error
|
||||
_LOGGER.debug("Requests remaining: %s", self.accuweather.requests_remaining)
|
||||
return {**current, **{ATTR_FORECAST: forecast}}
|
112
homeassistant/components/accuweather/config_flow.py
Normal file
112
homeassistant/components/accuweather/config_flow.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Adds config flow for AccuWeather."""
|
||||
import asyncio
|
||||
|
||||
from accuweather import AccuWeather, ApiError, InvalidApiKeyError, RequestsExceededError
|
||||
from aiohttp import ClientError
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
from async_timeout import timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
from .const import CONF_FORECAST, DOMAIN # pylint:disable=unused-import
|
||||
|
||||
|
||||
class AccuWeatherFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Config flow for AccuWeather."""
|
||||
|
||||
VERSION = 1
|
||||
CONNECTION_CLASS = config_entries.CONN_CLASS_CLOUD_POLL
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
# Under the terms of use of the API, one user can use one free API key. Due to
|
||||
# the small number of requests allowed, we only allow one integration instance.
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
errors = {}
|
||||
|
||||
if user_input is not None:
|
||||
websession = async_get_clientsession(self.hass)
|
||||
try:
|
||||
async with timeout(10):
|
||||
accuweather = AccuWeather(
|
||||
user_input[CONF_API_KEY],
|
||||
websession,
|
||||
latitude=user_input[CONF_LATITUDE],
|
||||
longitude=user_input[CONF_LONGITUDE],
|
||||
)
|
||||
await accuweather.async_get_location()
|
||||
except (ApiError, ClientConnectorError, asyncio.TimeoutError, ClientError):
|
||||
errors["base"] = "cannot_connect"
|
||||
except InvalidApiKeyError:
|
||||
errors[CONF_API_KEY] = "invalid_api_key"
|
||||
except RequestsExceededError:
|
||||
errors[CONF_API_KEY] = "requests_exceeded"
|
||||
else:
|
||||
await self.async_set_unique_id(
|
||||
accuweather.location_key, raise_on_progress=False
|
||||
)
|
||||
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_NAME], data=user_input
|
||||
)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Required(CONF_API_KEY): str,
|
||||
vol.Optional(
|
||||
CONF_LATITUDE, default=self.hass.config.latitude
|
||||
): cv.latitude,
|
||||
vol.Optional(
|
||||
CONF_LONGITUDE, default=self.hass.config.longitude
|
||||
): cv.longitude,
|
||||
vol.Optional(
|
||||
CONF_NAME, default=self.hass.config.location_name
|
||||
): str,
|
||||
}
|
||||
),
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
def async_get_options_flow(config_entry):
|
||||
"""Options callback for AccuWeather."""
|
||||
return AccuWeatherOptionsFlowHandler(config_entry)
|
||||
|
||||
|
||||
class AccuWeatherOptionsFlowHandler(config_entries.OptionsFlow):
|
||||
"""Config flow options for AccuWeather."""
|
||||
|
||||
def __init__(self, config_entry):
|
||||
"""Initialize AccuWeather options flow."""
|
||||
self.config_entry = config_entry
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
"""Manage the options."""
|
||||
return await self.async_step_user()
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow initialized by the user."""
|
||||
if user_input is not None:
|
||||
return self.async_create_entry(title="", data=user_input)
|
||||
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(
|
||||
{
|
||||
vol.Optional(
|
||||
CONF_FORECAST,
|
||||
default=self.config_entry.options.get(CONF_FORECAST, False),
|
||||
): bool
|
||||
}
|
||||
),
|
||||
)
|
279
homeassistant/components/accuweather/const.py
Normal file
279
homeassistant/components/accuweather/const.py
Normal file
@@ -0,0 +1,279 @@
|
||||
"""Constants for AccuWeather integration."""
|
||||
from homeassistant.const import (
|
||||
ATTR_DEVICE_CLASS,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
LENGTH_FEET,
|
||||
LENGTH_INCHES,
|
||||
LENGTH_METERS,
|
||||
LENGTH_MILLIMETERS,
|
||||
PERCENTAGE,
|
||||
SPEED_KILOMETERS_PER_HOUR,
|
||||
SPEED_MILES_PER_HOUR,
|
||||
TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT,
|
||||
TIME_HOURS,
|
||||
UV_INDEX,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
|
||||
ATTRIBUTION = "Data provided by AccuWeather"
|
||||
ATTR_ICON = "icon"
|
||||
ATTR_FORECAST = CONF_FORECAST = "forecast"
|
||||
ATTR_LABEL = "label"
|
||||
ATTR_UNIT_IMPERIAL = "Imperial"
|
||||
ATTR_UNIT_METRIC = "Metric"
|
||||
CONCENTRATION_PARTS_PER_CUBIC_METER = f"p/{VOLUME_CUBIC_METERS}"
|
||||
COORDINATOR = "coordinator"
|
||||
DOMAIN = "accuweather"
|
||||
MANUFACTURER = "AccuWeather, Inc."
|
||||
NAME = "AccuWeather"
|
||||
UNDO_UPDATE_LISTENER = "undo_update_listener"
|
||||
|
||||
CONDITION_CLASSES = {
|
||||
"clear-night": [33, 34, 37],
|
||||
"cloudy": [7, 8, 38],
|
||||
"exceptional": [24, 30, 31],
|
||||
"fog": [11],
|
||||
"hail": [25],
|
||||
"lightning": [15],
|
||||
"lightning-rainy": [16, 17, 41, 42],
|
||||
"partlycloudy": [4, 6, 35, 36],
|
||||
"pouring": [18],
|
||||
"rainy": [12, 13, 14, 26, 39, 40],
|
||||
"snowy": [19, 20, 21, 22, 23, 43, 44],
|
||||
"snowy-rainy": [29],
|
||||
"sunny": [1, 2, 3, 5],
|
||||
"windy": [32],
|
||||
}
|
||||
|
||||
FORECAST_DAYS = [0, 1, 2, 3, 4]
|
||||
|
||||
FORECAST_SENSOR_TYPES = {
|
||||
"CloudCoverDay": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-cloudy",
|
||||
ATTR_LABEL: "Cloud Cover Day",
|
||||
ATTR_UNIT_METRIC: PERCENTAGE,
|
||||
ATTR_UNIT_IMPERIAL: PERCENTAGE,
|
||||
},
|
||||
"CloudCoverNight": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-cloudy",
|
||||
ATTR_LABEL: "Cloud Cover Night",
|
||||
ATTR_UNIT_METRIC: PERCENTAGE,
|
||||
ATTR_UNIT_IMPERIAL: PERCENTAGE,
|
||||
},
|
||||
"Grass": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:grass",
|
||||
ATTR_LABEL: "Grass Pollen",
|
||||
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
},
|
||||
"HoursOfSun": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-partly-cloudy",
|
||||
ATTR_LABEL: "Hours Of Sun",
|
||||
ATTR_UNIT_METRIC: TIME_HOURS,
|
||||
ATTR_UNIT_IMPERIAL: TIME_HOURS,
|
||||
},
|
||||
"Mold": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:blur",
|
||||
ATTR_LABEL: "Mold Pollen",
|
||||
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
},
|
||||
"Ozone": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:vector-triangle",
|
||||
ATTR_LABEL: "Ozone",
|
||||
ATTR_UNIT_METRIC: None,
|
||||
ATTR_UNIT_IMPERIAL: None,
|
||||
},
|
||||
"Ragweed": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:sprout",
|
||||
ATTR_LABEL: "Ragweed Pollen",
|
||||
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
},
|
||||
"RealFeelTemperatureMax": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature Max",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"RealFeelTemperatureMin": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature Min",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"RealFeelTemperatureShadeMax": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature Shade Max",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"RealFeelTemperatureShadeMin": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature Shade Min",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"ThunderstormProbabilityDay": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-lightning",
|
||||
ATTR_LABEL: "Thunderstorm Probability Day",
|
||||
ATTR_UNIT_METRIC: PERCENTAGE,
|
||||
ATTR_UNIT_IMPERIAL: PERCENTAGE,
|
||||
},
|
||||
"ThunderstormProbabilityNight": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-lightning",
|
||||
ATTR_LABEL: "Thunderstorm Probability Night",
|
||||
ATTR_UNIT_METRIC: PERCENTAGE,
|
||||
ATTR_UNIT_IMPERIAL: PERCENTAGE,
|
||||
},
|
||||
"Tree": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:tree-outline",
|
||||
ATTR_LABEL: "Tree Pollen",
|
||||
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||
},
|
||||
"UVIndex": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-sunny",
|
||||
ATTR_LABEL: "UV Index",
|
||||
ATTR_UNIT_METRIC: UV_INDEX,
|
||||
ATTR_UNIT_IMPERIAL: UV_INDEX,
|
||||
},
|
||||
"WindGustDay": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-windy",
|
||||
ATTR_LABEL: "Wind Gust Day",
|
||||
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR,
|
||||
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR,
|
||||
},
|
||||
"WindGustNight": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-windy",
|
||||
ATTR_LABEL: "Wind Gust Night",
|
||||
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR,
|
||||
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR,
|
||||
},
|
||||
}
|
||||
|
||||
OPTIONAL_SENSORS = (
|
||||
"ApparentTemperature",
|
||||
"CloudCover",
|
||||
"CloudCoverDay",
|
||||
"CloudCoverNight",
|
||||
"DewPoint",
|
||||
"Grass",
|
||||
"Mold",
|
||||
"Ozone",
|
||||
"Ragweed",
|
||||
"RealFeelTemperatureShade",
|
||||
"RealFeelTemperatureShadeMax",
|
||||
"RealFeelTemperatureShadeMin",
|
||||
"Tree",
|
||||
"WetBulbTemperature",
|
||||
"WindChillTemperature",
|
||||
"WindGust",
|
||||
"WindGustDay",
|
||||
"WindGustNight",
|
||||
)
|
||||
|
||||
SENSOR_TYPES = {
|
||||
"ApparentTemperature": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "Apparent Temperature",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"Ceiling": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-fog",
|
||||
ATTR_LABEL: "Cloud Ceiling",
|
||||
ATTR_UNIT_METRIC: LENGTH_METERS,
|
||||
ATTR_UNIT_IMPERIAL: LENGTH_FEET,
|
||||
},
|
||||
"CloudCover": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-cloudy",
|
||||
ATTR_LABEL: "Cloud Cover",
|
||||
ATTR_UNIT_METRIC: PERCENTAGE,
|
||||
ATTR_UNIT_IMPERIAL: PERCENTAGE,
|
||||
},
|
||||
"DewPoint": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "Dew Point",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"RealFeelTemperature": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"RealFeelTemperatureShade": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "RealFeel Temperature Shade",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"Precipitation": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-rainy",
|
||||
ATTR_LABEL: "Precipitation",
|
||||
ATTR_UNIT_METRIC: LENGTH_MILLIMETERS,
|
||||
ATTR_UNIT_IMPERIAL: LENGTH_INCHES,
|
||||
},
|
||||
"PressureTendency": {
|
||||
ATTR_DEVICE_CLASS: "accuweather__pressure_tendency",
|
||||
ATTR_ICON: "mdi:gauge",
|
||||
ATTR_LABEL: "Pressure Tendency",
|
||||
ATTR_UNIT_METRIC: None,
|
||||
ATTR_UNIT_IMPERIAL: None,
|
||||
},
|
||||
"UVIndex": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-sunny",
|
||||
ATTR_LABEL: "UV Index",
|
||||
ATTR_UNIT_METRIC: UV_INDEX,
|
||||
ATTR_UNIT_IMPERIAL: UV_INDEX,
|
||||
},
|
||||
"WetBulbTemperature": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "Wet Bulb Temperature",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"WindChillTemperature": {
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE,
|
||||
ATTR_ICON: None,
|
||||
ATTR_LABEL: "Wind Chill Temperature",
|
||||
ATTR_UNIT_METRIC: TEMP_CELSIUS,
|
||||
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT,
|
||||
},
|
||||
"WindGust": {
|
||||
ATTR_DEVICE_CLASS: None,
|
||||
ATTR_ICON: "mdi:weather-windy",
|
||||
ATTR_LABEL: "Wind Gust",
|
||||
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR,
|
||||
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR,
|
||||
},
|
||||
}
|
9
homeassistant/components/accuweather/manifest.json
Normal file
9
homeassistant/components/accuweather/manifest.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"domain": "accuweather",
|
||||
"name": "AccuWeather",
|
||||
"documentation": "https://www.home-assistant.io/integrations/accuweather/",
|
||||
"requirements": ["accuweather==0.0.11"],
|
||||
"codeowners": ["@bieniu"],
|
||||
"config_flow": true,
|
||||
"quality_scale": "platinum"
|
||||
}
|
165
homeassistant/components/accuweather/sensor.py
Normal file
165
homeassistant/components/accuweather/sensor.py
Normal file
@@ -0,0 +1,165 @@
|
||||
"""Support for the AccuWeather service."""
|
||||
from homeassistant.const import (
|
||||
ATTR_ATTRIBUTION,
|
||||
ATTR_DEVICE_CLASS,
|
||||
CONF_NAME,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
)
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .const import (
|
||||
ATTR_FORECAST,
|
||||
ATTR_ICON,
|
||||
ATTR_LABEL,
|
||||
ATTRIBUTION,
|
||||
COORDINATOR,
|
||||
DOMAIN,
|
||||
FORECAST_DAYS,
|
||||
FORECAST_SENSOR_TYPES,
|
||||
MANUFACTURER,
|
||||
NAME,
|
||||
OPTIONAL_SENSORS,
|
||||
SENSOR_TYPES,
|
||||
)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Add AccuWeather entities from a config_entry."""
|
||||
name = config_entry.data[CONF_NAME]
|
||||
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR]
|
||||
|
||||
sensors = []
|
||||
for sensor in SENSOR_TYPES:
|
||||
sensors.append(AccuWeatherSensor(name, sensor, coordinator))
|
||||
|
||||
if coordinator.forecast:
|
||||
for sensor in FORECAST_SENSOR_TYPES:
|
||||
for day in FORECAST_DAYS:
|
||||
# Some air quality/allergy sensors are only available for certain
|
||||
# locations.
|
||||
if sensor in coordinator.data[ATTR_FORECAST][0]:
|
||||
sensors.append(
|
||||
AccuWeatherSensor(name, sensor, coordinator, forecast_day=day)
|
||||
)
|
||||
|
||||
async_add_entities(sensors, False)
|
||||
|
||||
|
||||
class AccuWeatherSensor(CoordinatorEntity):
|
||||
"""Define an AccuWeather entity."""
|
||||
|
||||
def __init__(self, name, kind, coordinator, forecast_day=None):
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator)
|
||||
self._name = name
|
||||
self.kind = kind
|
||||
self._device_class = None
|
||||
self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION}
|
||||
self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial"
|
||||
self.forecast_day = forecast_day
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
if self.forecast_day is not None:
|
||||
return f"{self._name} {FORECAST_SENSOR_TYPES[self.kind][ATTR_LABEL]} {self.forecast_day}d"
|
||||
return f"{self._name} {SENSOR_TYPES[self.kind][ATTR_LABEL]}"
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique_id for this entity."""
|
||||
if self.forecast_day is not None:
|
||||
return f"{self.coordinator.location_key}-{self.kind}-{self.forecast_day}".lower()
|
||||
return f"{self.coordinator.location_key}-{self.kind}".lower()
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.coordinator.location_key)},
|
||||
"name": NAME,
|
||||
"manufacturer": MANUFACTURER,
|
||||
"entry_type": "service",
|
||||
}
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state."""
|
||||
if self.forecast_day is not None:
|
||||
if (
|
||||
FORECAST_SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS]
|
||||
== DEVICE_CLASS_TEMPERATURE
|
||||
):
|
||||
return self.coordinator.data[ATTR_FORECAST][self.forecast_day][
|
||||
self.kind
|
||||
]["Value"]
|
||||
if self.kind in ["WindGustDay", "WindGustNight"]:
|
||||
return self.coordinator.data[ATTR_FORECAST][self.forecast_day][
|
||||
self.kind
|
||||
]["Speed"]["Value"]
|
||||
if self.kind in ["Grass", "Mold", "Ragweed", "Tree", "UVIndex", "Ozone"]:
|
||||
return self.coordinator.data[ATTR_FORECAST][self.forecast_day][
|
||||
self.kind
|
||||
]["Value"]
|
||||
return self.coordinator.data[ATTR_FORECAST][self.forecast_day][self.kind]
|
||||
if self.kind == "Ceiling":
|
||||
return round(self.coordinator.data[self.kind][self._unit_system]["Value"])
|
||||
if self.kind == "PressureTendency":
|
||||
return self.coordinator.data[self.kind]["LocalizedText"].lower()
|
||||
if SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS] == DEVICE_CLASS_TEMPERATURE:
|
||||
return self.coordinator.data[self.kind][self._unit_system]["Value"]
|
||||
if self.kind == "Precipitation":
|
||||
return self.coordinator.data["PrecipitationSummary"][self.kind][
|
||||
self._unit_system
|
||||
]["Value"]
|
||||
if self.kind == "WindGust":
|
||||
return self.coordinator.data[self.kind]["Speed"][self._unit_system]["Value"]
|
||||
return self.coordinator.data[self.kind]
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Return the icon."""
|
||||
if self.forecast_day is not None:
|
||||
return FORECAST_SENSOR_TYPES[self.kind][ATTR_ICON]
|
||||
return SENSOR_TYPES[self.kind][ATTR_ICON]
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the device_class."""
|
||||
if self.forecast_day is not None:
|
||||
return FORECAST_SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS]
|
||||
return SENSOR_TYPES[self.kind][ATTR_DEVICE_CLASS]
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit the value is expressed in."""
|
||||
if self.forecast_day is not None:
|
||||
return FORECAST_SENSOR_TYPES[self.kind][self._unit_system]
|
||||
return SENSOR_TYPES[self.kind][self._unit_system]
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
if self.forecast_day is not None:
|
||||
if self.kind in ["WindGustDay", "WindGustNight"]:
|
||||
self._attrs["direction"] = self.coordinator.data[ATTR_FORECAST][
|
||||
self.forecast_day
|
||||
][self.kind]["Direction"]["English"]
|
||||
elif self.kind in ["Grass", "Mold", "Ragweed", "Tree", "UVIndex", "Ozone"]:
|
||||
self._attrs["level"] = self.coordinator.data[ATTR_FORECAST][
|
||||
self.forecast_day
|
||||
][self.kind]["Category"]
|
||||
return self._attrs
|
||||
if self.kind == "UVIndex":
|
||||
self._attrs["level"] = self.coordinator.data["UVIndexText"]
|
||||
elif self.kind == "Precipitation":
|
||||
self._attrs["type"] = self.coordinator.data["PrecipitationType"]
|
||||
return self._attrs
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self):
|
||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||
return bool(self.kind not in OPTIONAL_SENSORS)
|
35
homeassistant/components/accuweather/strings.json
Normal file
35
homeassistant/components/accuweather/strings.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "AccuWeather",
|
||||
"description": "If you need help with the configuration have a look here: https://www.home-assistant.io/integrations/accuweather/\n\nSome sensors are not enabled by default. You can enable them in the entity registry after the integration configuration.\nWeather forecast is not enabled by default. You can enable it in the integration options.",
|
||||
"data": {
|
||||
"name": "Name of the integration",
|
||||
"api_key": "[%key:common::config_flow::data::api_key%]",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"invalid_api_key": "[%key:common::config_flow::error::invalid_api_key%]",
|
||||
"requests_exceeded": "The allowed number of requests to Accuweather API has been exceeded. You have to wait or change API Key."
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "AccuWeather Options",
|
||||
"description": "Due to the limitations of the free version of the AccuWeather API key, when you enable weather forecast, data updates will be performed every 64 minutes instead of every 32 minutes.",
|
||||
"data": {
|
||||
"forecast": "Weather forecast"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
homeassistant/components/accuweather/strings.sensor.json
Normal file
9
homeassistant/components/accuweather/strings.sensor.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"steady": "Steady",
|
||||
"rising": "Rising",
|
||||
"falling": "Falling"
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/ca.json
Normal file
35
homeassistant/components/accuweather/translations/ca.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ha fallat la connexi\u00f3",
|
||||
"invalid_api_key": "Clau API inv\u00e0lida",
|
||||
"requests_exceeded": "S'ha superat el nombre m\u00e0xim de sol\u00b7licituds permeses a l'API d'AccuWeather. Has d'esperar-te o canviar la clau API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clau API",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"name": "Nom de la integraci\u00f3"
|
||||
},
|
||||
"description": "Si necessites ajuda amb la configuraci\u00f3, consulta els seg\u00fcent enlla\u00e7: https://www.home-assistant.io/integrations/accuweather/ \n\n Alguns sensors no estan activats de manera predeterminada. Els pots activar des del registre d'entitats, despr\u00e9s de la configurraci\u00f3 de la integraci\u00f3.\n La previsi\u00f3 meteorol\u00f2gica no est\u00e0 activada de manera predeterminada. Pots activar-la en les opcions de la integraci\u00f3.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Previsi\u00f3 meteorol\u00f2gica"
|
||||
},
|
||||
"description": "Per culpa de les limitacions de la versi\u00f3 gratu\u00efta l'API d'AccuWeather, quan habilitis la previsi\u00f3 meteorol\u00f2gica, les actualitzacions es realitzaran cada 64 minuts en comptes de 32.",
|
||||
"title": "Opcions d'AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
homeassistant/components/accuweather/translations/cs.json
Normal file
12
homeassistant/components/accuweather/translations/cs.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"latitude": "Zem\u011bpisn\u00e1 \u0161\u00ed\u0159ka",
|
||||
"longitude": "Zem\u011bpisn\u00e1 d\u00e9lka"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
homeassistant/components/accuweather/translations/de.json
Normal file
13
homeassistant/components/accuweather/translations/de.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"latitude": "Breitengrad",
|
||||
"longitude": "L\u00e4ngengrad"
|
||||
},
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/en.json
Normal file
35
homeassistant/components/accuweather/translations/en.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Failed to connect",
|
||||
"invalid_api_key": "Invalid API key",
|
||||
"requests_exceeded": "The allowed number of requests to Accuweather API has been exceeded. You have to wait or change API Key."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Key",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"name": "Name of the integration"
|
||||
},
|
||||
"description": "If you need help with the configuration have a look here: https://www.home-assistant.io/integrations/accuweather/\n\nSome sensors are not enabled by default. You can enable them in the entity registry after the integration configuration.\nWeather forecast is not enabled by default. You can enable it in the integration options.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Weather forecast"
|
||||
},
|
||||
"description": "Due to the limitations of the free version of the AccuWeather API key, when you enable weather forecast, data updates will be performed every 64 minutes instead of every 32 minutes.",
|
||||
"title": "AccuWeather Options"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/es.json
Normal file
35
homeassistant/components/accuweather/translations/es.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ya est\u00e1 configurado. S\u00f3lo es posible una \u00fanica configuraci\u00f3n."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "No se pudo conectar",
|
||||
"invalid_api_key": "Clave API no v\u00e1lida",
|
||||
"requests_exceeded": "Se ha excedido el n\u00famero permitido de solicitudes a la API de Accuweather. Tienes que esperar o cambiar la Clave API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clave API",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"name": "Nombre de la integraci\u00f3n"
|
||||
},
|
||||
"description": "Si necesitas ayuda con la configuraci\u00f3n, echa un vistazo aqu\u00ed: https://www.home-assistant.io/integrations/accuweather/ \n\nEl pron\u00f3stico del tiempo no est\u00e1 habilitado por defecto. Puedes habilitarlo en las opciones de la integraci\u00f3n.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Pron\u00f3stico del tiempo"
|
||||
},
|
||||
"description": "Debido a las limitaciones de la versi\u00f3n gratuita de la clave API de AccuWeather, cuando habilitas el pron\u00f3stico del tiempo, las actualizaciones de datos se realizar\u00e1n cada 64 minutos en lugar de cada 32 minutos.",
|
||||
"title": "Opciones de AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/et.json
Normal file
35
homeassistant/components/accuweather/translations/et.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Sidumine juba tehtud. V\u00f5imalik on ainult 1 sidumine,"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u00dchendus eba\u00f5nnestus",
|
||||
"invalid_api_key": "API v\u00f5ti on vale",
|
||||
"requests_exceeded": "Accuweatheri API-le esitatud p\u00e4ringute piirarv on \u00fcletatud. Peate ootama (v\u00f5i muutma API v\u00f5tit)."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API v\u00f5ti",
|
||||
"latitude": "Laiuskraad",
|
||||
"longitude": "Pikkuskraad",
|
||||
"name": "Sidumise nimi"
|
||||
},
|
||||
"description": "Kui vajate seadistamisel abi vaadake siit: https://www.home-assistant.io/integrations/accuweather/ \n\n M\u00f5ni andur pole vaikimisi lubatud. P\u00e4rast sidumise seadistamist saate need \u00fcksused lubada. \n Ilmapennustus pole vaikimisi lubatud. Saate selle lubada sidumise s\u00e4tetes.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Ilmateade"
|
||||
},
|
||||
"description": "AccuWeather API tasuta versioonis toimub ilmaennustuse lubamisel andmete v\u00e4rskendamine iga 32 minuti asemel iga 64 minuti j\u00e4rel.",
|
||||
"title": "AccuWeatheri valikud"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/fr.json
Normal file
35
homeassistant/components/accuweather/translations/fr.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u00c9chec de connexion",
|
||||
"invalid_api_key": "Cl\u00e9 API invalide",
|
||||
"requests_exceeded": "Le nombre autoris\u00e9 de requ\u00eates adress\u00e9es \u00e0 l'API AccuWeather a \u00e9t\u00e9 d\u00e9pass\u00e9. Vous devez attendre ou modifier la cl\u00e9 API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Cl\u00e9 d'API",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"name": "Nom de l'int\u00e9gration"
|
||||
},
|
||||
"description": "Si vous avez besoin d'aide pour la configuration, consultez le site suivant : https://www.home-assistant.io/integrations/accuweather/\n\nCertains capteurs ne sont pas activ\u00e9s par d\u00e9faut. Vous pouvez les activer dans le registre des entit\u00e9s apr\u00e8s la configuration de l'int\u00e9gration.\nLes pr\u00e9visions m\u00e9t\u00e9orologiques ne sont pas activ\u00e9es par d\u00e9faut. Vous pouvez l'activer dans les options d'int\u00e9gration.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Pr\u00e9visions m\u00e9t\u00e9orologiques"
|
||||
},
|
||||
"description": "En raison des limitations de la version gratuite de la cl\u00e9 API AccuWeather, lorsque vous activez les pr\u00e9visions m\u00e9t\u00e9orologiques, les mises \u00e0 jour des donn\u00e9es seront effectu\u00e9es toutes les 64 minutes au lieu de toutes les 32 minutes.",
|
||||
"title": "Options AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/it.json
Normal file
35
homeassistant/components/accuweather/translations/it.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Impossibile connettersi",
|
||||
"invalid_api_key": "Chiave API non valida",
|
||||
"requests_exceeded": "\u00c8 stato superato il numero consentito di richieste all'API di Accuweather. \u00c8 necessario attendere o modificare la chiave API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Chiave API",
|
||||
"latitude": "Latitudine",
|
||||
"longitude": "Logitudine",
|
||||
"name": "Nome dell'integrazione"
|
||||
},
|
||||
"description": "Se hai bisogno di aiuto con la configurazione dai un'occhiata qui: https://www.home-assistant.io/integrations/accuweather/ \n\nAlcuni sensori non sono abilitati per impostazione predefinita. \u00c8 possibile abilitarli nel registro entit\u00e0 dopo la configurazione di integrazione. \nLe previsioni meteo non sono abilitate per impostazione predefinita. Puoi abilitarle nelle opzioni di integrazione.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Previsioni meteo"
|
||||
},
|
||||
"description": "A causa delle limitazioni della versione gratuita della chiave API AccuWeather, quando si abilitano le previsioni del tempo, gli aggiornamenti dei dati verranno eseguiti ogni 64 minuti invece che ogni 32 minuti.",
|
||||
"title": "Opzioni AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"description": "\uad6c\uc131\uc5d0 \ub300\ud55c \ub3c4\uc6c0\uc774 \ud544\uc694\ud55c \uacbd\uc6b0 \ub2e4\uc74c\uc744 \ucc38\uc870\ud574\uc8fc\uc138\uc694:\nhttps://www.home-assistant.io/integrations/accuweather/\n\n\uc77c\ubd80 \uc13c\uc11c\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc5f0\ub3d9 \uad6c\uc131 \ud6c4 \uad6c\uc131\uc694\uc18c \ub808\uc9c0\uc2a4\ud2b8\ub9ac\uc5d0\uc11c \ud65c\uc131\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.\n\uc77c\uae30\uc608\ubcf4\ub294 \uae30\ubcf8\uc801\uc73c\ub85c \ud65c\uc131\ud654\ub418\uc5b4 \uc788\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4. \uc5f0\ub3d9 \uc635\uc158\uc5d0\uc11c \ud65c\uc131\ud654\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/lb.json
Normal file
35
homeassistant/components/accuweather/translations/lb.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun ass m\u00e9iglech."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Feeler beim verbannen",
|
||||
"invalid_api_key": "Ong\u00ebltegen API Schl\u00ebssel",
|
||||
"requests_exceeded": "D\u00e9i zougelooss Zuel vun Ufroen un Accuweather API gouf iwwerschratt. Du muss ofwaarden oder den API Schl\u00ebssel \u00e4nneren."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Schl\u00ebssel",
|
||||
"latitude": "Breedegrad",
|
||||
"longitude": "L\u00e4ngegrad",
|
||||
"name": "Numm vun der Integratioun"
|
||||
},
|
||||
"description": "Falls du H\u00ebllef mat der Konfiguratioun brauch kuck h\u00e9i:\nhttps://www.home-assistant.io/integrations/accuweather/\n\nWieder Pr\u00e9visounen si standardm\u00e9isseg net aktiv. Du kanns d\u00e9i an den Optioune vun der Integratioun aschalten.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Wieder Pr\u00e9visioun"
|
||||
},
|
||||
"description": "Duerch d'Limite vun der Gratis Versioun vun der AccuWeather API, wann d'Wieder Pr\u00e9visoune aktiv\u00e9iert sinn, ginn d'Aktualis\u00e9ierungen all 64 Minutten gemaach, am plaatz vun all 32 Minutten.",
|
||||
"title": "AccuWeather Optiounen"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/no.json
Normal file
35
homeassistant/components/accuweather/translations/no.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Tilkobling mislyktes.",
|
||||
"invalid_api_key": "Ugyldig API-n\u00f8kkel",
|
||||
"requests_exceeded": "Det tillatte antallet foresp\u00f8rsler til Accuweather API er overskredet. Du m\u00e5 vente eller endre API-n\u00f8kkel."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API-n\u00f8kkel",
|
||||
"latitude": "Breddegrad",
|
||||
"longitude": "Lengdegrad",
|
||||
"name": "Navn p\u00e5 integrasjon"
|
||||
},
|
||||
"description": "Hvis du trenger hjelp med konfigurasjonen, kan du se her: https://www.home-assistant.io/integrations/accuweather/ \n\n Noen sensorer er ikke aktivert som standard. Du kan aktivere dem i enhetsregisteret etter integrasjonskonfigurasjonen. \n V\u00e6rmelding er ikke aktivert som standard. Du kan aktivere det i integrasjonsalternativene.",
|
||||
"title": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "V\u00e6rmelding"
|
||||
},
|
||||
"description": "P\u00e5 grunn av begrensningene i gratisversjonen av AccuWeather API-n\u00f8kkelen, n\u00e5r du aktiverer v\u00e6rmelding, vil dataoppdateringer bli utf\u00f8rt hvert 64. minutt i stedet for hvert 32. minutt.",
|
||||
"title": "AccuWeather-alternativer"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/pl.json
Normal file
35
homeassistant/components/accuweather/translations/pl.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia",
|
||||
"invalid_api_key": "Nieprawid\u0142owy klucz API.",
|
||||
"requests_exceeded": "Dozwolona liczba zapyta\u0144 do interfejsu API AccuWeather zosta\u0142a przekroczona. Musisz poczeka\u0107 lub zmieni\u0107 klucz API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Klucz API",
|
||||
"latitude": "Szeroko\u015b\u0107 geograficzna",
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"name": "Nazwa integracji"
|
||||
},
|
||||
"description": "Je\u015bli potrzebujesz pomocy z konfiguracj\u0105, przejd\u017a na stron\u0119: https://www.home-assistant.io/integrations/accuweather/ \n\nCz\u0119\u015b\u0107 sensor\u00f3w nie jest w\u0142\u0105czona domy\u015blnie. Mo\u017cesz je w\u0142\u0105czy\u0107 w rejestrze encji po konfiguracji integracji.\nPrognoza pogody nie jest domy\u015blnie w\u0142\u0105czona. Mo\u017cesz j\u0105 w\u0142\u0105czy\u0107 w opcjach integracji.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Prognoza pogody"
|
||||
},
|
||||
"description": "Ze wzgl\u0119du na ograniczenia darmowej wersji klucza API AccuWeather po w\u0142\u0105czeniu prognozy pogody aktualizacje danych b\u0119d\u0105 wykonywane co 64 minut zamiast co 32 minut.",
|
||||
"title": "Opcje AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
homeassistant/components/accuweather/translations/pt-BR.json
Normal file
24
homeassistant/components/accuweather/translations/pt-BR.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Chave API",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude"
|
||||
},
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Previs\u00e3o do Tempo"
|
||||
},
|
||||
"description": "Devido \u00e0s limita\u00e7\u00f5es da vers\u00e3o gratuita da chave da API AccuWeather, quando voc\u00ea habilita a previs\u00e3o do tempo, as atualiza\u00e7\u00f5es de dados ser\u00e3o realizadas a cada 64 minutos em vez de a cada 32 minutos."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
homeassistant/components/accuweather/translations/pt.json
Normal file
29
homeassistant/components/accuweather/translations/pt.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Falha na liga\u00e7\u00e3o",
|
||||
"invalid_api_key": "Chave de API inv\u00e1lida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Chave de API",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "Previs\u00e3o meteorol\u00f3gica"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
35
homeassistant/components/accuweather/translations/ru.json
Normal file
35
homeassistant/components/accuweather/translations/ru.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e."
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c\u0441\u044f.",
|
||||
"invalid_api_key": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API.",
|
||||
"requests_exceeded": "\u041f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u043e \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043a API Accuweather. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u043e\u0434\u043e\u0436\u0434\u0430\u0442\u044c \u0438\u043b\u0438 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043a\u043b\u044e\u0447 API."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "\u041a\u043b\u044e\u0447 API",
|
||||
"latitude": "\u0428\u0438\u0440\u043e\u0442\u0430",
|
||||
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
||||
"name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"
|
||||
},
|
||||
"description": "\u041e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f\u043c\u0438, \u0435\u0441\u043b\u0438 \u0412\u0430\u043c \u043d\u0443\u0436\u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0441 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u043e\u0439:\nhttps://www.home-assistant.io/integrations/accuweather/ \n\n\u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u043d\u0441\u043e\u0440\u044b \u0441\u043a\u0440\u044b\u0442\u044b \u0438 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0443\u0436\u043d\u044b\u0445 \u0441\u0435\u043d\u0441\u043e\u0440\u043e\u0432 \u0432 \u0440\u0435\u0435\u0441\u0442\u0440\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438 \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b \u0432 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "\u041f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u044b"
|
||||
},
|
||||
"description": "\u0412 \u0441\u0432\u044f\u0437\u0438 \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u043a\u043b\u044e\u0447\u0430 API AccuWeather, \u043f\u0440\u0438 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u043d\u043e\u0437\u0430 \u043f\u043e\u0433\u043e\u0434\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442\u044c \u043a\u0430\u0436\u0434\u044b\u0435 64 \u043c\u0438\u043d\u0443\u0442\u044b, \u0430 \u043d\u0435 \u043a\u0430\u0436\u0434\u044b\u0435 32 \u043c\u0438\u043d\u0443\u0442\u044b.",
|
||||
"title": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AccuWeather"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Disminuint",
|
||||
"rising": "Augmentant",
|
||||
"steady": "Estable"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Klesaj\u00edc\u00ed",
|
||||
"rising": "Roustouc\u00ed",
|
||||
"steady": "St\u00e1l\u00fd"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Falling",
|
||||
"rising": "Rising",
|
||||
"steady": "Steady"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Cayendo",
|
||||
"rising": "Subiendo",
|
||||
"steady": "Estable"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Langev",
|
||||
"rising": "T\u00f5usev",
|
||||
"steady": "\u00dchtlane"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "En baisse",
|
||||
"rising": "En hausse",
|
||||
"steady": "Stable"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Diminuzione",
|
||||
"rising": "Aumento",
|
||||
"steady": "Stabile"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "R\u00e9ckleefeg",
|
||||
"rising": "Erh\u00e9ijung",
|
||||
"steady": "Stabil"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "Fallende",
|
||||
"rising": "Stiger",
|
||||
"steady": "Jevn"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "spada",
|
||||
"rising": "ro\u015bnie",
|
||||
"steady": "bez zmian"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "\u041f\u043e\u043d\u0438\u0436\u0430\u044e\u0449\u0435\u0435\u0441\u044f",
|
||||
"rising": "\u041f\u043e\u0432\u044b\u0448\u0430\u044e\u0449\u0435\u0435\u0441\u044f",
|
||||
"steady": "\u041f\u043e\u0441\u0442\u043e\u044f\u043d\u043d\u043e\u0435"
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"state": {
|
||||
"accuweather__pressure_tendency": {
|
||||
"falling": "\u4e0b\u964d",
|
||||
"rising": "\u4e0a\u5347",
|
||||
"steady": "\u7a69\u5b9a"
|
||||
}
|
||||
}
|
||||
}
|
26
homeassistant/components/accuweather/translations/uk.json
Normal file
26
homeassistant/components/accuweather/translations/uk.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"invalid_api_key": "\u0425\u0438\u0431\u043d\u0438\u0439 \u043a\u043b\u044e\u0447 API"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"latitude": "\u0428\u0438\u0440\u043e\u0442\u0430",
|
||||
"longitude": "\u0414\u043e\u0432\u0433\u043e\u0442\u0430",
|
||||
"name": "\u041d\u0430\u0437\u0432\u0430 \u0456\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0456\u0457"
|
||||
},
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "\u041f\u0440\u043e\u0433\u043d\u043e\u0437 \u043f\u043e\u0433\u043e\u0434\u0438"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u50c5\u80fd\u8a2d\u5b9a\u4e00\u7d44\u8a2d\u5099\u3002"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "\u9023\u7dda\u5931\u6557",
|
||||
"invalid_api_key": "API \u5bc6\u9470\u7121\u6548",
|
||||
"requests_exceeded": "\u5df2\u8d85\u904e Accuweather API \u5141\u8a31\u7684\u8acb\u6c42\u6b21\u6578\u3002\u5fc5\u9808\u7b49\u5019\u6216\u8b8a\u66f4 API \u5bc6\u9470\u3002"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API \u5bc6\u9470",
|
||||
"latitude": "\u7def\u5ea6",
|
||||
"longitude": "\u7d93\u5ea6",
|
||||
"name": "\u6574\u5408\u540d\u7a31"
|
||||
},
|
||||
"description": "\u5047\u5982\u4f60\u9700\u8981\u5354\u52a9\u9032\u884c\u8a2d\u5b9a\uff0c\u8acb\u53c3\u95b1\uff1ahttps://www.home-assistant.io/integrations/accuweather/\n\n\u67d0\u4e9b\u50b3\u611f\u5668\u9810\u8a2d\u70ba\u672a\u555f\u7528\uff0c\u53ef\u4ee5\u65bc\u6574\u5408\u8a2d\u5b9a\u4e2d\u555f\u7528\u9019\u4e9b\u5be6\u9ad4\u3002\u5929\u6c23\u9810\u5831\u9810\u8a2d\u672a\u958b\u555f\u3002\u53ef\u4ee5\u65bc\u6574\u5408\u9078\u9805\u4e2d\u958b\u555f\u3002",
|
||||
"title": "AccuWeather"
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"forecast": "\u5929\u6c23\u9810\u5831"
|
||||
},
|
||||
"description": "\u7531\u65bc AccuWeather API \u5bc6\u9470\u514d\u8cbb\u7248\u672c\u9650\u5236\uff0c\u7576\u958b\u555f\u5929\u6c23\u9810\u5831\u6642\u3001\u6578\u64da\u6703\u6bcf 64 \u5206\u9418\u66f4\u65b0\u4e00\u6b21\uff0c\u800c\u975e 32 \u5206\u9418\u3002",
|
||||
"title": "AccuWeather \u9078\u9805"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
176
homeassistant/components/accuweather/weather.py
Normal file
176
homeassistant/components/accuweather/weather.py
Normal file
@@ -0,0 +1,176 @@
|
||||
"""Support for the AccuWeather service."""
|
||||
from statistics import mean
|
||||
|
||||
from homeassistant.components.weather import (
|
||||
ATTR_FORECAST_CONDITION,
|
||||
ATTR_FORECAST_PRECIPITATION,
|
||||
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
|
||||
ATTR_FORECAST_TEMP,
|
||||
ATTR_FORECAST_TEMP_LOW,
|
||||
ATTR_FORECAST_TIME,
|
||||
ATTR_FORECAST_WIND_BEARING,
|
||||
ATTR_FORECAST_WIND_SPEED,
|
||||
WeatherEntity,
|
||||
)
|
||||
from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from homeassistant.util.dt import utc_from_timestamp
|
||||
|
||||
from .const import (
|
||||
ATTR_FORECAST,
|
||||
ATTRIBUTION,
|
||||
CONDITION_CLASSES,
|
||||
COORDINATOR,
|
||||
DOMAIN,
|
||||
MANUFACTURER,
|
||||
NAME,
|
||||
)
|
||||
|
||||
PARALLEL_UPDATES = 1
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"""Add a AccuWeather weather entity from a config_entry."""
|
||||
name = config_entry.data[CONF_NAME]
|
||||
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][COORDINATOR]
|
||||
|
||||
async_add_entities([AccuWeatherEntity(name, coordinator)], False)
|
||||
|
||||
|
||||
class AccuWeatherEntity(CoordinatorEntity, WeatherEntity):
|
||||
"""Define an AccuWeather entity."""
|
||||
|
||||
def __init__(self, name, coordinator):
|
||||
"""Initialize."""
|
||||
super().__init__(coordinator)
|
||||
self._name = name
|
||||
self._attrs = {}
|
||||
self._unit_system = "Metric" if self.coordinator.is_metric else "Imperial"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def attribution(self):
|
||||
"""Return the attribution."""
|
||||
return ATTRIBUTION
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique_id for this entity."""
|
||||
return self.coordinator.location_key
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return the device info."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.coordinator.location_key)},
|
||||
"name": NAME,
|
||||
"manufacturer": MANUFACTURER,
|
||||
"entry_type": "service",
|
||||
}
|
||||
|
||||
@property
|
||||
def condition(self):
|
||||
"""Return the current condition."""
|
||||
try:
|
||||
return [
|
||||
k
|
||||
for k, v in CONDITION_CLASSES.items()
|
||||
if self.coordinator.data["WeatherIcon"] in v
|
||||
][0]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@property
|
||||
def temperature(self):
|
||||
"""Return the temperature."""
|
||||
return self.coordinator.data["Temperature"][self._unit_system]["Value"]
|
||||
|
||||
@property
|
||||
def temperature_unit(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS if self.coordinator.is_metric else TEMP_FAHRENHEIT
|
||||
|
||||
@property
|
||||
def pressure(self):
|
||||
"""Return the pressure."""
|
||||
return self.coordinator.data["Pressure"][self._unit_system]["Value"]
|
||||
|
||||
@property
|
||||
def humidity(self):
|
||||
"""Return the humidity."""
|
||||
return self.coordinator.data["RelativeHumidity"]
|
||||
|
||||
@property
|
||||
def wind_speed(self):
|
||||
"""Return the wind speed."""
|
||||
return self.coordinator.data["Wind"]["Speed"][self._unit_system]["Value"]
|
||||
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the wind bearing."""
|
||||
return self.coordinator.data["Wind"]["Direction"]["Degrees"]
|
||||
|
||||
@property
|
||||
def visibility(self):
|
||||
"""Return the visibility."""
|
||||
return self.coordinator.data["Visibility"][self._unit_system]["Value"]
|
||||
|
||||
@property
|
||||
def ozone(self):
|
||||
"""Return the ozone level."""
|
||||
# We only have ozone data for certain locations and only in the forecast data.
|
||||
if self.coordinator.forecast and self.coordinator.data[ATTR_FORECAST][0].get(
|
||||
"Ozone"
|
||||
):
|
||||
return self.coordinator.data[ATTR_FORECAST][0]["Ozone"]["Value"]
|
||||
return None
|
||||
|
||||
@property
|
||||
def forecast(self):
|
||||
"""Return the forecast array."""
|
||||
if not self.coordinator.forecast:
|
||||
return None
|
||||
# remap keys from library to keys understood by the weather component
|
||||
forecast = [
|
||||
{
|
||||
ATTR_FORECAST_TIME: utc_from_timestamp(item["EpochDate"]).isoformat(),
|
||||
ATTR_FORECAST_TEMP: item["TemperatureMax"]["Value"],
|
||||
ATTR_FORECAST_TEMP_LOW: item["TemperatureMin"]["Value"],
|
||||
ATTR_FORECAST_PRECIPITATION: self._calc_precipitation(item),
|
||||
ATTR_FORECAST_PRECIPITATION_PROBABILITY: round(
|
||||
mean(
|
||||
[
|
||||
item["PrecipitationProbabilityDay"],
|
||||
item["PrecipitationProbabilityNight"],
|
||||
]
|
||||
)
|
||||
),
|
||||
ATTR_FORECAST_WIND_SPEED: item["WindDay"]["Speed"]["Value"],
|
||||
ATTR_FORECAST_WIND_BEARING: item["WindDay"]["Direction"]["Degrees"],
|
||||
ATTR_FORECAST_CONDITION: [
|
||||
k for k, v in CONDITION_CLASSES.items() if item["IconDay"] in v
|
||||
][0],
|
||||
}
|
||||
for item in self.coordinator.data[ATTR_FORECAST]
|
||||
]
|
||||
return forecast
|
||||
|
||||
@staticmethod
|
||||
def _calc_precipitation(day: dict) -> float:
|
||||
"""Return sum of the precipitation."""
|
||||
precip_sum = 0
|
||||
precip_types = ["Rain", "Snow", "Ice"]
|
||||
for precip in precip_types:
|
||||
precip_sum = sum(
|
||||
[
|
||||
precip_sum,
|
||||
day[f"{precip}Day"]["Value"],
|
||||
day[f"{precip}Night"]["Value"],
|
||||
]
|
||||
)
|
||||
return round(precip_sum, 1)
|
@@ -26,10 +26,8 @@ class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
if (
|
||||
user_input is not None
|
||||
and self.discovered_hubs is not None
|
||||
# pylint: disable=unsupported-membership-test
|
||||
and user_input["id"] in self.discovered_hubs
|
||||
):
|
||||
# pylint: disable=unsubscriptable-object
|
||||
return await self.async_create(self.discovered_hubs[user_input["id"]])
|
||||
|
||||
# Already configured hosts
|
||||
|
@@ -61,7 +61,7 @@ class AcmedaCover(AcmedaBase, CoverEntity):
|
||||
None is unknown, 0 is closed, 100 is fully open.
|
||||
"""
|
||||
position = None
|
||||
if self.roller.type == 7 or self.roller.type == 10:
|
||||
if self.roller.type in [7, 10]:
|
||||
position = 100 - self.roller.closed_percent
|
||||
return position
|
||||
|
||||
@@ -86,37 +86,36 @@ class AcmedaCover(AcmedaBase, CoverEntity):
|
||||
@property
|
||||
def is_closed(self):
|
||||
"""Return if the cover is closed."""
|
||||
is_closed = self.roller.closed_percent == 100
|
||||
return is_closed
|
||||
return self.roller.closed_percent == 100
|
||||
|
||||
async def close_cover(self, **kwargs):
|
||||
async def async_close_cover(self, **kwargs):
|
||||
"""Close the roller."""
|
||||
await self.roller.move_down()
|
||||
|
||||
async def open_cover(self, **kwargs):
|
||||
async def async_open_cover(self, **kwargs):
|
||||
"""Open the roller."""
|
||||
await self.roller.move_up()
|
||||
|
||||
async def stop_cover(self, **kwargs):
|
||||
async def async_stop_cover(self, **kwargs):
|
||||
"""Stop the roller."""
|
||||
await self.roller.move_stop()
|
||||
|
||||
async def set_cover_position(self, **kwargs):
|
||||
async def async_set_cover_position(self, **kwargs):
|
||||
"""Move the roller shutter to a specific position."""
|
||||
await self.roller.move_to(100 - kwargs[ATTR_POSITION])
|
||||
|
||||
async def close_cover_tilt(self, **kwargs):
|
||||
async def async_close_cover_tilt(self, **kwargs):
|
||||
"""Close the roller."""
|
||||
await self.roller.move_down()
|
||||
|
||||
async def open_cover_tilt(self, **kwargs):
|
||||
async def async_open_cover_tilt(self, **kwargs):
|
||||
"""Open the roller."""
|
||||
await self.roller.move_up()
|
||||
|
||||
async def stop_cover_tilt(self, **kwargs):
|
||||
async def async_stop_cover_tilt(self, **kwargs):
|
||||
"""Stop the roller."""
|
||||
await self.roller.move_stop()
|
||||
|
||||
async def set_cover_tilt(self, **kwargs):
|
||||
async def async_set_cover_tilt(self, **kwargs):
|
||||
"""Tilt the roller shutter to a specific position."""
|
||||
await self.roller.move_to(100 - kwargs[ATTR_POSITION])
|
||||
|
@@ -37,5 +37,6 @@ async def update_devices(hass, config_entry, api):
|
||||
)
|
||||
if device is not None:
|
||||
dev_registry.async_update_device(
|
||||
device.id, name=api_item.name,
|
||||
device.id,
|
||||
name=api_item.name,
|
||||
)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
"""Support for Acmeda Roller Blind Batteries."""
|
||||
from homeassistant.const import DEVICE_CLASS_BATTERY, UNIT_PERCENTAGE
|
||||
from homeassistant.const import DEVICE_CLASS_BATTERY, PERCENTAGE
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
|
||||
@@ -33,7 +33,7 @@ class AcmedaBattery(AcmedaBase):
|
||||
"""Representation of a Acmeda cover device."""
|
||||
|
||||
device_class = DEVICE_CLASS_BATTERY
|
||||
unit_of_measurement = UNIT_PERCENTAGE
|
||||
unit_of_measurement = PERCENTAGE
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@@ -1,5 +1,4 @@
|
||||
"""Support for AdGuard Home."""
|
||||
from distutils.version import LooseVersion
|
||||
import logging
|
||||
from typing import Any, Dict
|
||||
|
||||
@@ -11,7 +10,6 @@ from homeassistant.components.adguard.const import (
|
||||
DATA_ADGUARD_CLIENT,
|
||||
DATA_ADGUARD_VERION,
|
||||
DOMAIN,
|
||||
MIN_ADGUARD_HOME_VERSION,
|
||||
SERVICE_ADD_URL,
|
||||
SERVICE_DISABLE_URL,
|
||||
SERVICE_ENABLE_URL,
|
||||
@@ -67,16 +65,10 @@ async def async_setup_entry(hass: HomeAssistantType, entry: ConfigEntry) -> bool
|
||||
hass.data.setdefault(DOMAIN, {})[DATA_ADGUARD_CLIENT] = adguard
|
||||
|
||||
try:
|
||||
version = await adguard.version()
|
||||
await adguard.version()
|
||||
except AdGuardHomeConnectionError as exception:
|
||||
raise ConfigEntryNotReady from exception
|
||||
|
||||
if version and LooseVersion(MIN_ADGUARD_HOME_VERSION) > LooseVersion(version):
|
||||
_LOGGER.error(
|
||||
"This integration requires AdGuard Home v0.99.0 or higher to work correctly"
|
||||
)
|
||||
raise ConfigEntryNotReady
|
||||
|
||||
for component in "sensor", "switch":
|
||||
hass.async_create_task(
|
||||
hass.config_entries.async_forward_entry_setup(entry, component)
|
||||
@@ -183,7 +175,7 @@ class AdGuardHomeEntity(Entity):
|
||||
except AdGuardHomeError:
|
||||
if self._available:
|
||||
_LOGGER.debug(
|
||||
"An error occurred while updating AdGuard Home sensor.",
|
||||
"An error occurred while updating AdGuard Home sensor",
|
||||
exc_info=True,
|
||||
)
|
||||
self._available = False
|
||||
|
@@ -1,12 +1,11 @@
|
||||
"""Config flow to configure the AdGuard Home integration."""
|
||||
from distutils.version import LooseVersion
|
||||
import logging
|
||||
|
||||
from adguardhome import AdGuardHome, AdGuardHomeConnectionError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.adguard.const import DOMAIN, MIN_ADGUARD_HOME_VERSION
|
||||
from homeassistant.components.adguard.const import DOMAIN
|
||||
from homeassistant.config_entries import ConfigFlow
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
@@ -79,20 +78,11 @@ class AdGuardHomeFlowHandler(ConfigFlow):
|
||||
)
|
||||
|
||||
try:
|
||||
version = await adguard.version()
|
||||
await adguard.version()
|
||||
except AdGuardHomeConnectionError:
|
||||
errors["base"] = "connection_error"
|
||||
return await self._show_setup_form(errors)
|
||||
|
||||
if version and LooseVersion(MIN_ADGUARD_HOME_VERSION) > LooseVersion(version):
|
||||
return self.async_abort(
|
||||
reason="adguard_home_outdated",
|
||||
description_placeholders={
|
||||
"current_version": version,
|
||||
"minimal_version": MIN_ADGUARD_HOME_VERSION,
|
||||
},
|
||||
)
|
||||
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_HOST],
|
||||
data={
|
||||
@@ -160,20 +150,11 @@ class AdGuardHomeFlowHandler(ConfigFlow):
|
||||
)
|
||||
|
||||
try:
|
||||
version = await adguard.version()
|
||||
await adguard.version()
|
||||
except AdGuardHomeConnectionError:
|
||||
errors["base"] = "connection_error"
|
||||
return await self._show_hassio_form(errors)
|
||||
|
||||
if LooseVersion(MIN_ADGUARD_HOME_VERSION) > LooseVersion(version):
|
||||
return self.async_abort(
|
||||
reason="adguard_home_addon_outdated",
|
||||
description_placeholders={
|
||||
"current_version": version,
|
||||
"minimal_version": MIN_ADGUARD_HOME_VERSION,
|
||||
},
|
||||
)
|
||||
|
||||
return self.async_create_entry(
|
||||
title=self._hassio_discovery["addon"],
|
||||
data={
|
||||
|
@@ -7,8 +7,6 @@ DATA_ADGUARD_VERION = "adguard_version"
|
||||
|
||||
CONF_FORCE = "force"
|
||||
|
||||
MIN_ADGUARD_HOME_VERSION = "v0.99.0"
|
||||
|
||||
SERVICE_ADD_URL = "add_url"
|
||||
SERVICE_DISABLE_URL = "disable_url"
|
||||
SERVICE_ENABLE_URL = "enable_url"
|
||||
|
@@ -11,7 +11,7 @@ from homeassistant.components.adguard.const import (
|
||||
DOMAIN,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import TIME_MILLISECONDS, UNIT_PERCENTAGE
|
||||
from homeassistant.const import PERCENTAGE, TIME_MILLISECONDS
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
@@ -134,7 +134,7 @@ class AdGuardHomePercentageBlockedSensor(AdGuardHomeSensor):
|
||||
"AdGuard DNS Queries Blocked Ratio",
|
||||
"mdi:magnify-close",
|
||||
"blocked_percentage",
|
||||
UNIT_PERCENTAGE,
|
||||
PERCENTAGE,
|
||||
)
|
||||
|
||||
async def _adguard_update(self) -> None:
|
||||
|
@@ -19,8 +19,6 @@
|
||||
},
|
||||
"error": { "connection_error": "Failed to connect." },
|
||||
"abort": {
|
||||
"adguard_home_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}.",
|
||||
"adguard_home_addon_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}. Please update your Hass.io AdGuard Home add-on.",
|
||||
"existing_instance_updated": "Updated existing configuration.",
|
||||
"single_instance_allowed": "Only a single configuration of AdGuard Home is allowed."
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ class AdGuardHomeSwitch(AdGuardHomeDeviceEntity, SwitchEntity):
|
||||
try:
|
||||
await self._adguard_turn_off()
|
||||
except AdGuardHomeError:
|
||||
_LOGGER.error("An error occurred while turning off AdGuard Home switch.")
|
||||
_LOGGER.error("An error occurred while turning off AdGuard Home switch")
|
||||
self._available = False
|
||||
|
||||
async def _adguard_turn_off(self) -> None:
|
||||
@@ -85,7 +85,7 @@ class AdGuardHomeSwitch(AdGuardHomeDeviceEntity, SwitchEntity):
|
||||
try:
|
||||
await self._adguard_turn_on()
|
||||
except AdGuardHomeError:
|
||||
_LOGGER.error("An error occurred while turning on AdGuard Home switch.")
|
||||
_LOGGER.error("An error occurred while turning on AdGuard Home switch")
|
||||
self._available = False
|
||||
|
||||
async def _adguard_turn_on(self) -> None:
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}. \u041c\u043e\u043b\u044f, \u0430\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u0439\u0442\u0435 \u0432\u0430\u0448\u0430\u0442\u0430 \u0434\u043e\u0431\u0430\u0432\u043a\u0430 \u0437\u0430 Hass.io AdGuard Home.",
|
||||
"adguard_home_outdated": "\u0422\u0430\u0437\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0438\u0437\u0438\u0441\u043a\u0432\u0430 AdGuard Home {minimal_version} \u0438\u043b\u0438 \u043f\u043e-\u043d\u043e\u0432\u0430 {minimal_version}, \u0438\u043c\u0430\u0442\u0435 {current_version}.",
|
||||
"existing_instance_updated": "\u0410\u043a\u0442\u0443\u0430\u043b\u0438\u0437\u0438\u0440\u0430\u043d\u0435 \u043d\u0430 \u0441\u044a\u0449\u0435\u0441\u0442\u0432\u0443\u0432\u0430\u0449\u0430\u0442\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f.",
|
||||
"single_instance_allowed": "\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f \u043d\u0430 AdGuard Home."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Aquesta integraci\u00f3 necessita la versi\u00f3 d'AdGuard Home {minimal_version} o una superior, tens la {current_version}. Actualitza el complement de Hass.io d'AdGuard Home.",
|
||||
"adguard_home_outdated": "Aquesta integraci\u00f3 necessita la versi\u00f3 d'AdGuard Home {minimal_version} o una superior, tens la {current_version}.",
|
||||
"existing_instance_updated": "S'ha actualitzat la configuraci\u00f3 existent.",
|
||||
"single_instance_allowed": "Nom\u00e9s es permet una \u00fanica configuraci\u00f3 d'AdGuard Home."
|
||||
},
|
||||
|
@@ -4,6 +4,14 @@
|
||||
"hassio_confirm": {
|
||||
"description": "Chcete nakonfigurovat slu\u017ebu Home Assistant pro p\u0159ipojen\u00ed k AddGuard pomoc\u00ed hass.io {addon}?",
|
||||
"title": "AdGuard prost\u0159ednictv\u00edm dopl\u0148ku Hass.io"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Hostitel",
|
||||
"password": "Heslo",
|
||||
"port": "Port",
|
||||
"username": "U\u017eivatelsk\u00e9 jm\u00e9no"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Denne integration kr\u00e6ver AdGuard Home {minimal_version} eller h\u00f8jere, du har {current_version}. Opdater venligst din Hass.io AdGuard Home-tilf\u00f8jelse.",
|
||||
"adguard_home_outdated": "Denne integration kr\u00e6ver AdGuard Home {minimal_version} eller h\u00f8jere, du har {current_version}.",
|
||||
"existing_instance_updated": "Opdaterede eksisterende konfiguration.",
|
||||
"single_instance_allowed": "Kun en enkelt konfiguration af AdGuard Home er tilladt."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Diese Integration erfordert AdGuard Home {minimal_version} oder h\u00f6her, du hast {current_version}. Bitte aktualisiere dein Hass.io AdGuard Home Add-on.",
|
||||
"adguard_home_outdated": "Diese Integration erfordert AdGuard Home {minimal_version} oder h\u00f6her, du hast {current_version}.",
|
||||
"existing_instance_updated": "Bestehende Konfiguration wurde aktualisiert.",
|
||||
"single_instance_allowed": "Es ist nur eine einzige Konfiguration von AdGuard Home zul\u00e4ssig."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}. Please update your Hass.io AdGuard Home add-on.",
|
||||
"adguard_home_outdated": "This integration requires AdGuard Home {minimal_version} or higher, you have {current_version}.",
|
||||
"existing_instance_updated": "Updated existing configuration.",
|
||||
"single_instance_allowed": "Only a single configuration of AdGuard Home is allowed."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, tiene {current_version}. Actualice su complemento Hass.io AdGuard Home.",
|
||||
"adguard_home_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, tiene {current_version}.",
|
||||
"existing_instance_updated": "Se actualiz\u00f3 la configuraci\u00f3n existente.",
|
||||
"single_instance_allowed": "Solo se permite una \u00fanica configuraci\u00f3n de AdGuard Home."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, usted tiene {current_version}. Por favor, actualice su complemento Hass.io AdGuard Home.",
|
||||
"adguard_home_outdated": "Esta integraci\u00f3n requiere AdGuard Home {minimal_version} o superior, usted tiene {current_version}.",
|
||||
"existing_instance_updated": "Se ha actualizado la configuraci\u00f3n existente.",
|
||||
"single_instance_allowed": "S\u00f3lo se permite una \u00fanica configuraci\u00f3n de AdGuard Home."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Cette int\u00e9gration n\u00e9cessite AdGuard Home {minimal_version} ou une version ult\u00e9rieure, vous disposez de {current_version}. Veuillez mettre \u00e0 jour votre compl\u00e9ment Hass.io AdGuard Home.",
|
||||
"adguard_home_outdated": "Cette int\u00e9gration n\u00e9cessite AdGuard Home {minimal_version} ou une version ult\u00e9rieure, vous disposez de {current_version}.",
|
||||
"existing_instance_updated": "La configuration existante a \u00e9t\u00e9 mise \u00e0 jour.",
|
||||
"single_instance_allowed": "Une seule configuration d'AdGuard Home est autoris\u00e9e."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}. Aggiorna il componente aggiuntivo AdGuard Home di Hass.io.",
|
||||
"adguard_home_outdated": "Questa integrazione richiede AdGuard Home {minimal_version} o versione successiva, si dispone di {current_version}.",
|
||||
"existing_instance_updated": "Configurazione esistente aggiornata.",
|
||||
"single_instance_allowed": "\u00c8 consentita solo una singola configurazione di AdGuard Home."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "\uc774 \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\ub294 AdGuard Home {minimal_version} \uc774\uc0c1\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \ud604\uc7ac \ubc84\uc804\uc740 {current_version} \uc785\ub2c8\ub2e4. Hass.io AdGuard Home \uc560\ub4dc\uc628\uc744 \uc5c5\ub370\uc774\ud2b8 \ud574\uc8fc\uc138\uc694.",
|
||||
"adguard_home_outdated": "\uc774 \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\ub294 AdGuard Home {minimal_version} \uc774\uc0c1\uc774 \ud544\uc694\ud569\ub2c8\ub2e4. \ud604\uc7ac \ubc84\uc804\uc740 {current_version} \uc785\ub2c8\ub2e4.",
|
||||
"existing_instance_updated": "\uae30\uc874 \uad6c\uc131\uc744 \uc5c5\ub370\uc774\ud2b8\ud588\uc2b5\ub2c8\ub2e4.",
|
||||
"single_instance_allowed": "\ud558\ub098\uc758 AdGuard Home \ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
|
||||
},
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"adguard_home_addon_outdated": "D\u00ebs Integratioun ben\u00e9idegt AdgGuard Home {minimal_version} oder m\u00e9i, dir hutt {current_version}. Aktualis\u00e9iert w.e.g. \u00e4ren Hass.io AdGuard Home Add-on.",
|
||||
"adguard_home_outdated": "D\u00ebs Integratioun ben\u00e9idegt AdgGuard Home {minimal_version} oder m\u00e9i, dir hutt {current_version}.",
|
||||
"existing_instance_updated": "D\u00e9i bestehend Konfiguratioun ass ge\u00e4nnert.",
|
||||
"single_instance_allowed": "N\u00ebmmen eng eenzeg Konfiguratioun vun AdGuard Home ass erlaabt."
|
||||
},
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user