mirror of
https://github.com/micahqcade/custom_vesync.git
synced 2025-03-11 23:30:11 +01:00
first commit
This commit is contained in:
commit
79938b9f19
1
Config/.HA_VERSION
Normal file
1
Config/.HA_VERSION
Normal file
@ -0,0 +1 @@
|
||||
2022.3.8
|
122
Config/.storage/auth
Normal file
122
Config/.storage/auth
Normal file
@ -0,0 +1,122 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "auth",
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"id": "563d33967d924c588c6ecbff5eb96ed8",
|
||||
"group_ids": [
|
||||
"system-read-only"
|
||||
],
|
||||
"is_owner": false,
|
||||
"is_active": true,
|
||||
"name": "Home Assistant Content",
|
||||
"system_generated": true,
|
||||
"local_only": false
|
||||
},
|
||||
{
|
||||
"id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"group_ids": [
|
||||
"system-admin"
|
||||
],
|
||||
"is_owner": true,
|
||||
"is_active": true,
|
||||
"name": "vlb",
|
||||
"system_generated": false,
|
||||
"local_only": false
|
||||
}
|
||||
],
|
||||
"groups": [
|
||||
{
|
||||
"id": "system-admin",
|
||||
"name": "Administrators"
|
||||
},
|
||||
{
|
||||
"id": "system-users",
|
||||
"name": "Users"
|
||||
},
|
||||
{
|
||||
"id": "system-read-only",
|
||||
"name": "Read Only"
|
||||
}
|
||||
],
|
||||
"credentials": [
|
||||
{
|
||||
"id": "9beb9518028c4616948324f9e7e2d071",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"auth_provider_type": "homeassistant",
|
||||
"auth_provider_id": null,
|
||||
"data": {
|
||||
"username": "vlb"
|
||||
}
|
||||
}
|
||||
],
|
||||
"refresh_tokens": [
|
||||
{
|
||||
"id": "a3f4e8066389495ea030efd0bf0d5cd4",
|
||||
"user_id": "563d33967d924c588c6ecbff5eb96ed8",
|
||||
"client_id": null,
|
||||
"client_name": null,
|
||||
"client_icon": null,
|
||||
"token_type": "system",
|
||||
"created_at": "2022-04-01T07:45:31.978398+00:00",
|
||||
"access_token_expiration": 1800.0,
|
||||
"token": "e4059f19c8a74f70691dafb6f8f67c7dddc2f6389020cb6c7d9a5596a0eedee4e523e8ef00c56f2e06ebe8eda4c26a26f12764a9802cf24c876e2f8f09418a50",
|
||||
"jwt_key": "38697b84f9313b5652b1f8d85022617e8cc7ef3c6299225cc28af8e519694818ef3634c106e53c1f6e5bda25c17079c61a06fd0ba661800a642cd7d9f350c29c",
|
||||
"last_used_at": null,
|
||||
"last_used_ip": null,
|
||||
"credential_id": null,
|
||||
"version": "2022.3.8"
|
||||
},
|
||||
{
|
||||
"id": "58d1aab125b742f98856591680c886f8",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"client_id": "https://test.tiarkaerell.com/",
|
||||
"client_name": null,
|
||||
"client_icon": null,
|
||||
"token_type": "normal",
|
||||
"created_at": "2022-04-01T08:04:48.046872+00:00",
|
||||
"access_token_expiration": 1800.0,
|
||||
"token": "149461688179de15bb59d25377c890569b12a53cd3607a132d80089cdaa8e4539bc51bfd2b26e93a4574517181c245dfdd8a4b7dbd9fa58b110a834f4ac07306",
|
||||
"jwt_key": "4516dea1cd209768b3918cdb9023464f08778c3f853511dbf524328abbd70e232c5808fd60c05b59fa500e30cfeef24d5c4fafed357965ecdab9c4a3dbd8123d",
|
||||
"last_used_at": "2022-04-01T08:04:48.047248+00:00",
|
||||
"last_used_ip": "85.195.218.245",
|
||||
"credential_id": "9beb9518028c4616948324f9e7e2d071",
|
||||
"version": "2022.3.8"
|
||||
},
|
||||
{
|
||||
"id": "e0c00138ce364f58af0fae84be751b11",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"client_id": "https://test.tiarkaerell.com/",
|
||||
"client_name": null,
|
||||
"client_icon": null,
|
||||
"token_type": "normal",
|
||||
"created_at": "2022-04-01T08:11:29.188371+00:00",
|
||||
"access_token_expiration": 1800.0,
|
||||
"token": "f3098610d7491485f26994ffcd37e51b32cd46d5719b1a5beab3063c61ca67d0eeb5c6416f1c77d01a420ab16465491cd3703cb1139018277d48476ac7c623de",
|
||||
"jwt_key": "b954d0236661f8bffcf6d25568c06ea906e6c141ea644eca94f50a382d5a84defb07526fca7e61558db216eb6d1d5039be8d1eb04db4ce1d36e50f9731745388",
|
||||
"last_used_at": "2022-04-01T10:28:18.393196+00:00",
|
||||
"last_used_ip": "85.195.218.245",
|
||||
"credential_id": "9beb9518028c4616948324f9e7e2d071",
|
||||
"version": "2022.3.8"
|
||||
},
|
||||
{
|
||||
"id": "c4fbf4356edf49a888812de23ecc63b6",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"client_id": "https://test.tiarkaerell.com/",
|
||||
"client_name": null,
|
||||
"client_icon": null,
|
||||
"token_type": "normal",
|
||||
"created_at": "2022-04-01T10:46:28.226111+00:00",
|
||||
"access_token_expiration": 1800.0,
|
||||
"token": "81f8a38953cc3f3ad6d4a1622baac99d94b1ba939b8388b27a6aff1da417538f67841ae07e23fed18674810b18b9eac1f539dbfae556b15df871a7c4ea7efd0e",
|
||||
"jwt_key": "5053a085fa4621225e4d53c3e26a934d2c92b418c1f98167e614a572d42d4381c526fae86e21f508014686645eb65a0c68c0821ec6c8e1a47e8fc59fe6fedb32",
|
||||
"last_used_at": "2022-04-01T10:46:28.227004+00:00",
|
||||
"last_used_ip": "84.74.113.94",
|
||||
"credential_id": "9beb9518028c4616948324f9e7e2d071",
|
||||
"version": "2022.3.8"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
13
Config/.storage/auth_provider.homeassistant
Normal file
13
Config/.storage/auth_provider.homeassistant
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "auth_provider.homeassistant",
|
||||
"data": {
|
||||
"users": [
|
||||
{
|
||||
"username": "vlb",
|
||||
"password": "JDJiJDEyJEg4Mkg2VHU5aXRCUjZPdmczUDNYQS5vVHplYjJIaUFUVDkyMmIuU1F6QVgvcUs2LnJhaTBt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
10
Config/.storage/core.analytics
Normal file
10
Config/.storage/core.analytics
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.analytics",
|
||||
"data": {
|
||||
"preferences": {},
|
||||
"onboarded": true,
|
||||
"uuid": null
|
||||
}
|
||||
}
|
24
Config/.storage/core.area_registry
Normal file
24
Config/.storage/core.area_registry
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.area_registry",
|
||||
"data": {
|
||||
"areas": [
|
||||
{
|
||||
"name": "Salon",
|
||||
"id": "salon",
|
||||
"picture": null
|
||||
},
|
||||
{
|
||||
"name": "Cuisine",
|
||||
"id": "cuisine",
|
||||
"picture": null
|
||||
},
|
||||
{
|
||||
"name": "Chambre",
|
||||
"id": "chambre",
|
||||
"picture": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
16
Config/.storage/core.config
Normal file
16
Config/.storage/core.config
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.config",
|
||||
"data": {
|
||||
"latitude": 52.3731339,
|
||||
"longitude": 4.8903147,
|
||||
"elevation": 0,
|
||||
"unit_system": "metric",
|
||||
"location_name": "Maison",
|
||||
"time_zone": "UTC",
|
||||
"external_url": null,
|
||||
"internal_url": null,
|
||||
"currency": "EUR"
|
||||
}
|
||||
}
|
38
Config/.storage/core.config_entries
Normal file
38
Config/.storage/core.config_entries
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.config_entries",
|
||||
"data": {
|
||||
"entries": [
|
||||
{
|
||||
"entry_id": "b869fb6b3dbead7e9a32f0712597fc22",
|
||||
"version": 1,
|
||||
"domain": "radio_browser",
|
||||
"title": "Radio Browser",
|
||||
"data": {},
|
||||
"options": {},
|
||||
"pref_disable_new_entities": false,
|
||||
"pref_disable_polling": false,
|
||||
"source": "onboarding",
|
||||
"unique_id": null,
|
||||
"disabled_by": null
|
||||
},
|
||||
{
|
||||
"entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"version": 1,
|
||||
"domain": "vesync",
|
||||
"title": "vlebourl@gmail.com",
|
||||
"data": {
|
||||
"username": "vlebourl@gmail.com",
|
||||
"password": "pVMMJG6NHTxFFC"
|
||||
},
|
||||
"options": {},
|
||||
"pref_disable_new_entities": false,
|
||||
"pref_disable_polling": false,
|
||||
"source": "user",
|
||||
"unique_id": "vlebourl@gmail.com-6838532",
|
||||
"disabled_by": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
34
Config/.storage/core.device_registry
Normal file
34
Config/.storage/core.device_registry
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 3,
|
||||
"key": "core.device_registry",
|
||||
"data": {
|
||||
"devices": [
|
||||
{
|
||||
"config_entries": [
|
||||
"0d5d11a7d4cf40ae0800a418ed940bb3"
|
||||
],
|
||||
"connections": [],
|
||||
"identifiers": [
|
||||
[
|
||||
"vesync",
|
||||
"vsaq8556ccd84d7298c822b9bf950366"
|
||||
]
|
||||
],
|
||||
"manufacturer": "VeSync",
|
||||
"model": "LUH-D301S-WEU",
|
||||
"name": "Humidificateur",
|
||||
"sw_version": null,
|
||||
"hw_version": null,
|
||||
"entry_type": null,
|
||||
"id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"via_device_id": null,
|
||||
"area_id": null,
|
||||
"name_by_user": null,
|
||||
"disabled_by": null,
|
||||
"configuration_url": null
|
||||
}
|
||||
],
|
||||
"deleted_devices": []
|
||||
}
|
||||
}
|
264
Config/.storage/core.entity_registry
Normal file
264
Config/.storage/core.entity_registry
Normal file
@ -0,0 +1,264 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 5,
|
||||
"key": "core.entity_registry",
|
||||
"data": {
|
||||
"entities": [
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": null,
|
||||
"device_class": null,
|
||||
"device_id": null,
|
||||
"disabled_by": null,
|
||||
"entity_category": null,
|
||||
"entity_id": "person.vlb",
|
||||
"icon": null,
|
||||
"id": "cac156ee969a158d3d7f6eddc27a9f13",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "vlb",
|
||||
"platform": "person",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vlb",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "switch.humidificateur_display",
|
||||
"icon": null,
|
||||
"id": "61be826e1b8d0a297882c0479e99e5e5",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur display",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-display",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": {
|
||||
"state_class": "measurement"
|
||||
},
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "diagnostic",
|
||||
"entity_id": "sensor.humidificateur_current_humidity",
|
||||
"icon": null,
|
||||
"id": "99c7e35a8b96bd6b41db17687b94b693",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": "humidity",
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur current humidity",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-humidity",
|
||||
"unit_of_measurement": "%"
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "diagnostic",
|
||||
"entity_id": "binary_sensor.humidificateur_out_of_water",
|
||||
"icon": null,
|
||||
"id": "9444be2d2b974b2a8152532d74d88bad",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur out of water",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-out_of_water",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": {
|
||||
"min": 1,
|
||||
"max": 2,
|
||||
"step": 1.0,
|
||||
"mode": "auto"
|
||||
},
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "number.humidificateur_mist_level",
|
||||
"icon": null,
|
||||
"id": "4eb8ff6f14afee99ced44a973c9aab40",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur mist level",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-mist-level",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": {
|
||||
"min_humidity": 30,
|
||||
"max_humidity": 80,
|
||||
"available_modes": [
|
||||
"auto",
|
||||
"sleep",
|
||||
"manual"
|
||||
]
|
||||
},
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": null,
|
||||
"entity_id": "humidifier.humidificateur",
|
||||
"icon": null,
|
||||
"id": "d504532493c5e3835a04739c93a4fd0c",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur",
|
||||
"platform": "vesync",
|
||||
"supported_features": 1,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "switch.humidificateur_automatic_stop",
|
||||
"icon": null,
|
||||
"id": "ab61f5de2c2aa2b85b587c4b157298f5",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur automatic stop",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-automatic-stop",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "diagnostic",
|
||||
"entity_id": "binary_sensor.humidificateur_water_tank_lifted",
|
||||
"icon": null,
|
||||
"id": "9d1b97a64b64cb1689a1a01b8df694fe",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur water tank lifted",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-water_tank_lifted",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": {
|
||||
"min": 30,
|
||||
"max": 80,
|
||||
"step": 1.0,
|
||||
"mode": "auto"
|
||||
},
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "number.humidificateur_target_level",
|
||||
"icon": null,
|
||||
"id": "653aa2a575961a9d2677a83bc584a6ea",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur target level",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-target-level",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": null,
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "switch.humidificateur_auto_mode",
|
||||
"icon": null,
|
||||
"id": "8fcb923b00a0fe95b1ee0670eb1714aa",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur auto mode",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-auto-mode",
|
||||
"unit_of_measurement": null
|
||||
},
|
||||
{
|
||||
"area_id": null,
|
||||
"capabilities": {
|
||||
"supported_color_modes": [
|
||||
"brightness"
|
||||
]
|
||||
},
|
||||
"config_entry_id": "0d5d11a7d4cf40ae0800a418ed940bb3",
|
||||
"device_class": null,
|
||||
"device_id": "8fdadc0cedefbc28016545713ccc7f02",
|
||||
"disabled_by": null,
|
||||
"entity_category": "config",
|
||||
"entity_id": "light.humidificateur_night_light",
|
||||
"icon": null,
|
||||
"id": "66bf16efc1261a19c9c99db424275026",
|
||||
"name": null,
|
||||
"options": {},
|
||||
"original_device_class": null,
|
||||
"original_icon": null,
|
||||
"original_name": "Humidificateur night light",
|
||||
"platform": "vesync",
|
||||
"supported_features": 0,
|
||||
"unique_id": "vsaq8556ccd84d7298c822b9bf950366-night-light",
|
||||
"unit_of_measurement": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
28
Config/.storage/core.restore_state
Normal file
28
Config/.storage/core.restore_state
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.restore_state",
|
||||
"data": [
|
||||
{
|
||||
"state": {
|
||||
"entity_id": "person.vlb",
|
||||
"state": "unknown",
|
||||
"attributes": {
|
||||
"editable": false,
|
||||
"id": "vlb",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"friendly_name": "vlb"
|
||||
},
|
||||
"last_changed": "2022-04-01T10:41:26.492401+00:00",
|
||||
"last_updated": "2022-04-01T10:41:30.405583+00:00",
|
||||
"context": {
|
||||
"id": "4916b780086bb9d8250804141e852b6f",
|
||||
"parent_id": null,
|
||||
"user_id": null
|
||||
}
|
||||
},
|
||||
"extra_data": null,
|
||||
"last_seen": "2022-04-01T10:56:55.367958+00:00"
|
||||
}
|
||||
]
|
||||
}
|
8
Config/.storage/core.uuid
Normal file
8
Config/.storage/core.uuid
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "core.uuid",
|
||||
"data": {
|
||||
"uuid": "3b5ed1182c11445a93dc24d7737bf468"
|
||||
}
|
||||
}
|
18
Config/.storage/http
Normal file
18
Config/.storage/http
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "http",
|
||||
"data": {
|
||||
"server_port": 9443,
|
||||
"use_x_forwarded_for": true,
|
||||
"trusted_proxies": [
|
||||
"192.168.1.194"
|
||||
],
|
||||
"ip_ban_enabled": true,
|
||||
"cors_allowed_origins": [
|
||||
"https://cast.home-assistant.io"
|
||||
],
|
||||
"login_attempts_threshold": -1,
|
||||
"ssl_profile": "modern"
|
||||
}
|
||||
}
|
8
Config/.storage/http.auth
Normal file
8
Config/.storage/http.auth
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "http.auth",
|
||||
"data": {
|
||||
"content_user": "563d33967d924c588c6ecbff5eb96ed8"
|
||||
}
|
||||
}
|
13
Config/.storage/onboarding
Normal file
13
Config/.storage/onboarding
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": 4,
|
||||
"minor_version": 1,
|
||||
"key": "onboarding",
|
||||
"data": {
|
||||
"done": [
|
||||
"user",
|
||||
"core_config",
|
||||
"analytics",
|
||||
"integration"
|
||||
]
|
||||
}
|
||||
}
|
15
Config/.storage/person
Normal file
15
Config/.storage/person
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": 2,
|
||||
"minor_version": 1,
|
||||
"key": "person",
|
||||
"data": {
|
||||
"items": [
|
||||
{
|
||||
"name": "vlb",
|
||||
"user_id": "7e27048212fd43d78e900bed6f4ac44c",
|
||||
"device_trackers": [],
|
||||
"id": "vlb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
6
Config/.storage/trace.saved_traces
Normal file
6
Config/.storage/trace.saved_traces
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"version": 1,
|
||||
"minor_version": 1,
|
||||
"key": "trace.saved_traces",
|
||||
"data": {}
|
||||
}
|
1
Config/automations.yaml
Normal file
1
Config/automations.yaml
Normal file
@ -0,0 +1 @@
|
||||
[]
|
54
Config/blueprints/automation/homeassistant/motion_light.yaml
Normal file
54
Config/blueprints/automation/homeassistant/motion_light.yaml
Normal file
@ -0,0 +1,54 @@
|
||||
blueprint:
|
||||
name: Motion-activated Light
|
||||
description: Turn on a light when motion is detected.
|
||||
domain: automation
|
||||
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/motion_light.yaml
|
||||
input:
|
||||
motion_entity:
|
||||
name: Motion Sensor
|
||||
selector:
|
||||
entity:
|
||||
domain: binary_sensor
|
||||
device_class: motion
|
||||
light_target:
|
||||
name: Light
|
||||
selector:
|
||||
target:
|
||||
entity:
|
||||
domain: light
|
||||
no_motion_wait:
|
||||
name: Wait time
|
||||
description: Time to leave the light on after last motion is detected.
|
||||
default: 120
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 3600
|
||||
unit_of_measurement: seconds
|
||||
|
||||
# If motion is detected within the delay,
|
||||
# we restart the script.
|
||||
mode: restart
|
||||
max_exceeded: silent
|
||||
|
||||
trigger:
|
||||
platform: state
|
||||
entity_id: !input motion_entity
|
||||
from: "off"
|
||||
to: "on"
|
||||
|
||||
action:
|
||||
- alias: "Turn on the light"
|
||||
service: light.turn_on
|
||||
target: !input light_target
|
||||
- alias: "Wait until there is no motion from device"
|
||||
wait_for_trigger:
|
||||
platform: state
|
||||
entity_id: !input motion_entity
|
||||
from: "on"
|
||||
to: "off"
|
||||
- alias: "Wait the number of seconds that has been set"
|
||||
delay: !input no_motion_wait
|
||||
- alias: "Turn off the light"
|
||||
service: light.turn_off
|
||||
target: !input light_target
|
@ -0,0 +1,46 @@
|
||||
blueprint:
|
||||
name: Zone Notification
|
||||
description: Send a notification to a device when a person leaves a specific zone.
|
||||
domain: automation
|
||||
source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/automation/blueprints/notify_leaving_zone.yaml
|
||||
input:
|
||||
person_entity:
|
||||
name: Person
|
||||
selector:
|
||||
entity:
|
||||
domain: person
|
||||
zone_entity:
|
||||
name: Zone
|
||||
selector:
|
||||
entity:
|
||||
domain: zone
|
||||
notify_device:
|
||||
name: Device to notify
|
||||
description: Device needs to run the official Home Assistant app to receive notifications.
|
||||
selector:
|
||||
device:
|
||||
integration: mobile_app
|
||||
|
||||
trigger:
|
||||
platform: state
|
||||
entity_id: !input person_entity
|
||||
|
||||
variables:
|
||||
zone_entity: !input zone_entity
|
||||
# This is the state of the person when it's in this zone.
|
||||
zone_state: "{{ states[zone_entity].name }}"
|
||||
person_entity: !input person_entity
|
||||
person_name: "{{ states[person_entity].name }}"
|
||||
|
||||
condition:
|
||||
condition: template
|
||||
# The first case handles leaving the Home zone which has a special state when zoning called 'home'.
|
||||
# The second case handles leaving all other zones.
|
||||
value_template: "{{ zone_entity == 'zone.home' and trigger.from_state.state == 'home' and trigger.to_state.state != 'home' or trigger.from_state.state == zone_state and trigger.to_state.state != zone_state }}"
|
||||
|
||||
action:
|
||||
- alias: "Notify that a person has left the zone"
|
||||
domain: mobile_app
|
||||
type: notify
|
||||
device_id: !input notify_device
|
||||
message: "{{ person_name }} has left {{ zone_state }}"
|
@ -0,0 +1,84 @@
|
||||
blueprint:
|
||||
name: Confirmable Notification
|
||||
description: >-
|
||||
A script that sends an actionable notification with a confirmation before
|
||||
running the specified action.
|
||||
domain: script
|
||||
source_url: https://github.com/home-assistant/core/blob/master/homeassistant/components/script/blueprints/confirmable_notification.yaml
|
||||
input:
|
||||
notify_device:
|
||||
name: Device to notify
|
||||
description: Device needs to run the official Home Assistant app to receive notifications.
|
||||
selector:
|
||||
device:
|
||||
integration: mobile_app
|
||||
title:
|
||||
name: "Title"
|
||||
description: "The title of the button shown in the notification."
|
||||
default: ""
|
||||
selector:
|
||||
text:
|
||||
message:
|
||||
name: "Message"
|
||||
description: "The message body"
|
||||
selector:
|
||||
text:
|
||||
confirm_text:
|
||||
name: "Confirmation Text"
|
||||
description: "Text to show on the confirmation button"
|
||||
default: "Confirm"
|
||||
selector:
|
||||
text:
|
||||
confirm_action:
|
||||
name: "Confirmation Action"
|
||||
description: "Action to run when notification is confirmed"
|
||||
default: []
|
||||
selector:
|
||||
action:
|
||||
dismiss_text:
|
||||
name: "Dismiss Text"
|
||||
description: "Text to show on the dismiss button"
|
||||
default: "Dismiss"
|
||||
selector:
|
||||
text:
|
||||
dismiss_action:
|
||||
name: "Dismiss Action"
|
||||
description: "Action to run when notification is dismissed"
|
||||
default: []
|
||||
selector:
|
||||
action:
|
||||
|
||||
mode: restart
|
||||
|
||||
sequence:
|
||||
- alias: "Set up variables"
|
||||
variables:
|
||||
action_confirm: "{{ 'CONFIRM_' ~ context.id }}"
|
||||
action_dismiss: "{{ 'DISMISS_' ~ context.id }}"
|
||||
- alias: "Send notification"
|
||||
domain: mobile_app
|
||||
type: notify
|
||||
device_id: !input notify_device
|
||||
title: !input title
|
||||
message: !input message
|
||||
data:
|
||||
actions:
|
||||
- action: "{{ action_confirm }}"
|
||||
title: !input confirm_text
|
||||
- action: "{{ action_dismiss }}"
|
||||
title: !input dismiss_text
|
||||
- alias: "Awaiting response"
|
||||
wait_for_trigger:
|
||||
- platform: event
|
||||
event_type: mobile_app_notification_action
|
||||
event_data:
|
||||
action: "{{ action_confirm }}"
|
||||
- platform: event
|
||||
event_type: mobile_app_notification_action
|
||||
event_data:
|
||||
action: "{{ action_dismiss }}"
|
||||
- choose:
|
||||
- conditions: "{{ wait.trigger.event.data.action == action_confirm }}"
|
||||
sequence: !input confirm_action
|
||||
- conditions: "{{ wait.trigger.event.data.action == action_dismiss }}"
|
||||
sequence: !input dismiss_action
|
21
Config/configuration.yaml
Normal file
21
Config/configuration.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
# Configure a default setup of Home Assistant (frontend, api, etc)
|
||||
default_config:
|
||||
|
||||
# Text to speech
|
||||
tts:
|
||||
- platform: google_translate
|
||||
|
||||
http:
|
||||
server_port: 9443
|
||||
use_x_forwarded_for: true
|
||||
trusted_proxies:
|
||||
- 192.168.1.194
|
||||
|
||||
automation: !include automations.yaml
|
||||
script: !include scripts.yaml
|
||||
scene: !include scenes.yaml
|
||||
|
||||
logger:
|
||||
default: info
|
||||
logs:
|
||||
custom_components.vesync: debug
|
1
Config/custom_components
Symbolic link
1
Config/custom_components
Symbolic link
@ -0,0 +1 @@
|
||||
../custom_components
|
443
Config/home-assistant.log
Normal file
443
Config/home-assistant.log
Normal file
@ -0,0 +1,443 @@
|
||||
2022-04-01 12:41:25 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration vesync which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain logger took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up system_log
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain system_log took 0.0 seconds
|
||||
2022-04-01 12:41:25 WARNING (Recorder) [homeassistant.components.recorder.util] The system could not validate that the sqlite3 database at //home/vlb/temp/HAcore/vesync-bpo/Config/home-assistant_v2.db was shutdown cleanly
|
||||
2022-04-01 12:41:25 WARNING (Recorder) [homeassistant.components.recorder.util] Ended unfinished session (id=16 from 2022-04-01 10:28:05.941295)
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain recorder took 0.1 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 1: {'ssdp', 'lovelace', 'webhook', 'http', 'websocket_api', 'device_automation', 'person', 'zeroconf', 'analytics', 'dhcp', 'cloud', 'onboarding', 'api', 'usb', 'diagnostics', 'network', 'search', 'config', 'frontend', 'auth', 'image', 'system_log'}
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up lovelace
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up http
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up device_automation
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain device_automation took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up dhcp
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain dhcp took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain lovelace took 0.1 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.1 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up webhook
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain webhook took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up websocket_api
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain websocket_api took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up api
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain api took 0.0 seconds
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up diagnostics
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up config
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setting up auth
|
||||
2022-04-01 12:41:25 INFO (MainThread) [homeassistant.setup] Setup of domain auth took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain diagnostics took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain config took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up image
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up search
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain search took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up analytics
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_2) [homeassistant.loader] Loaded google_assistant from homeassistant.components.google_assistant
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_3) [homeassistant.loader] Loaded alexa from homeassistant.components.alexa
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up usb
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain usb took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up network
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain network took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain image took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain analytics took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_0) [homeassistant.loader] Loaded camera from homeassistant.components.camera
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up person
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_4) [homeassistant.loader] Loaded media_player from homeassistant.components.media_player
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up zeroconf
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up ssdp
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain ssdp took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain zeroconf took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up cloud
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain cloud took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain person took 0.3 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up onboarding
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain onboarding took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_0) [homeassistant.loader] Loaded hassio from homeassistant.components.hassio
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_4) [homeassistant.loader] Loaded device_tracker from homeassistant.components.device_tracker
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_3) [homeassistant.loader] Loaded group from homeassistant.components.group
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_2) [homeassistant.loader] Loaded panel_custom from homeassistant.components.panel_custom
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up frontend
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain frontend took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 2: {'energy', 'input_button', 'input_boolean', 'input_datetime', 'media_source', 'vesync', 'trace', 'history', 'map', 'tts', 'my', 'default_config', 'blueprint', 'input_number', 'counter', 'tag', 'input_select', 'zone', 'logbook', 'scene', 'mobile_app', 'automation', 'timer', 'system_health', 'sun', 'radio_browser', 'script', 'input_text'}
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_button
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_boolean
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_datetime
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up media_source
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up vesync
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain vesync took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up trace
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain trace took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up history
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain history took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up map
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain map took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up my
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain my took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up blueprint
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain blueprint took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_number
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up counter
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up tag
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_select
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up zone
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up logbook
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up scene
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.components.scene] Setting up scene.homeassistant
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up timer
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up system_health
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up sun
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain sun took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up radio_browser
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain radio_browser took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up input_text
|
||||
2022-04-01 12:41:26 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v1/user/login' api
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain media_source took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_0) [homeassistant.loader] Loaded tado from homeassistant.components.tado
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain logbook took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain scene took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up automation
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain system_health took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up script
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up energy
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain energy took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_1) [homeassistant.loader] Loaded google_translate from homeassistant.components.google_translate
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain automation took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain script took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_5) [homeassistant.loader] Loaded sensor from homeassistant.components.sensor
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up tts
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_button took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain tag took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_datetime took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_boolean took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_number took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.components.http] Now listening on port 9443
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setting up sensor
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain sensor took 0.0 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain counter took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_select took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.components.sensor] Setting up sensor.energy
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain zone took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain timer took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain input_text took 0.2 seconds
|
||||
2022-04-01 12:41:26 INFO (MainThread) [homeassistant.setup] Setup of domain tts took 0.1 seconds
|
||||
2022-04-01 12:41:26 INFO (SyncWorker_5) [homeassistant.loader] Loaded notify from homeassistant.components.notify
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setting up mobile_app
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setup of domain mobile_app took 0.0 seconds
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setting up notify
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setup of domain notify took 0.0 seconds
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setting up default_config
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.setup] Setup of domain default_config took 0.0 seconds
|
||||
2022-04-01 12:41:27 INFO (MainThread) [homeassistant.components.notify] Setting up notify.mobile_app
|
||||
2022-04-01 12:41:27 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v1/deviceManaged/devices' api
|
||||
2022-04-01 12:41:27 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.vesync] New device list initialized
|
||||
2022-04-01 12:41:27 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:28 INFO (MainThread) [custom_components.vesync.common] 1 VeSync fans found
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.sensor] Setting up sensor.vesync
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_1) [homeassistant.loader] Loaded switch from homeassistant.components.switch
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_5) [homeassistant.loader] Loaded fan from homeassistant.components.fan
|
||||
2022-04-01 12:41:28 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_3) [homeassistant.loader] Loaded light from homeassistant.components.light
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_2) [homeassistant.loader] Loaded number from homeassistant.components.number
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_1) [homeassistant.loader] Loaded binary_sensor from homeassistant.components.binary_sensor
|
||||
2022-04-01 12:41:28 INFO (SyncWorker_0) [homeassistant.loader] Loaded humidifier from homeassistant.components.humidifier
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up switch
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain switch took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up fan
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain fan took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up light
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up number
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain number took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up binary_sensor
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain binary_sensor took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setting up humidifier
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain humidifier took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.switch] Setting up switch.vesync
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.fan] Setting up fan.vesync
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.setup] Setup of domain light took 0.0 seconds
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.number] Setting up number.vesync
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up binary_sensor.vesync
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.humidifier] Setting up humidifier.vesync
|
||||
2022-04-01 12:41:28 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:28 INFO (MainThread) [homeassistant.components.light] Setting up light.vesync
|
||||
2022-04-01 12:41:28 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:28 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:28 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:29 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:29 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:29 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:30 INFO (MainThread) [homeassistant.bootstrap] Home Assistant initialized in 5.01s
|
||||
2022-04-01 12:41:30 INFO (MainThread) [homeassistant.core] Starting Home Assistant
|
||||
2022-04-01 12:41:30 INFO (MainThread) [homeassistant.core] Timer:starting
|
||||
2022-04-01 12:41:30 INFO (MainThread) [homeassistant.components.zeroconf] Starting Zeroconf broadcast
|
||||
2022-04-01 12:41:30 INFO (SyncWorker_3) [homeassistant.loader] Loaded overkiz from homeassistant.components.overkiz
|
||||
2022-04-01 12:41:30 INFO (SyncWorker_1) [homeassistant.loader] Loaded hue from homeassistant.components.hue
|
||||
2022-04-01 12:41:31 INFO (SyncWorker_4) [homeassistant.loader] Loaded somfy from homeassistant.components.somfy
|
||||
2022-04-01 12:41:31 INFO (SyncWorker_4) [homeassistant.loader] Loaded upnp from homeassistant.components.upnp
|
||||
2022-04-01 12:41:31 INFO (SyncWorker_5) [homeassistant.loader] Loaded cast from homeassistant.components.cast
|
||||
2022-04-01 12:41:31 INFO (SyncWorker_1) [homeassistant.loader] Loaded plex from homeassistant.components.plex
|
||||
2022-04-01 12:41:31 INFO (SyncWorker_0) [homeassistant.loader] Loaded homekit_controller from homeassistant.components.homekit_controller
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_3) [homeassistant.loader] Loaded netatmo from homeassistant.components.netatmo
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_2) [homeassistant.loader] Loaded ipp from homeassistant.components.ipp
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_4) [homeassistant.loader] Loaded esphome from homeassistant.components.esphome
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_5) [homeassistant.loader] Loaded harmony from homeassistant.components.harmony
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_1) [homeassistant.loader] Loaded remote from homeassistant.components.remote
|
||||
2022-04-01 12:41:32 INFO (MainThread) [homeassistant.setup] Setting up remote
|
||||
2022-04-01 12:41:32 INFO (MainThread) [homeassistant.setup] Setup of domain remote took 0.0 seconds
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_3) [homeassistant.loader] Loaded dlna_dms from homeassistant.components.dlna_dms
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_2) [homeassistant.loader] Loaded devolo_home_control from homeassistant.components.devolo_home_control
|
||||
2022-04-01 12:41:32 INFO (SyncWorker_4) [homeassistant.loader] Loaded devolo_home_network from homeassistant.components.devolo_home_network
|
||||
2022-04-01 12:41:59 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:59 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:01 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:29 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:30 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:31 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:31 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:59 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:42:59 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:01 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:01 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:29 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:30 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:31 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:31 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:59 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:43:59 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:01 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:01 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:29 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:29 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:29 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:30 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:31 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:31 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:59 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:44:59 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:01 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:29 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:30 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:59 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:45:59 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:01 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:01 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:29 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:30 DEBUG (SyncWorker_9) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:30 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:31 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:31 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:46:59 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:00 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:00 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:01 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:02 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:29 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:29 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:30 DEBUG (SyncWorker_9) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:31 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:47:59 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:01 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:29 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:29 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:30 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:31 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:48:59 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:00 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:01 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:01 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:29 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:29 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:30 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:31 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:49:59 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:00 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:01 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:01 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:29 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:30 DEBUG (SyncWorker_9) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:31 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:50:59 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:00 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:01 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:29 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:29 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:30 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:31 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:51:59 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:00 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:01 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:01 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:01 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:29 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:29 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:30 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:30 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:31 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:52:59 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:00 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:00 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:01 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:01 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:29 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:29 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:30 DEBUG (SyncWorker_9) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:31 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:53:59 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:00 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:00 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:01 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:01 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:29 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:30 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:30 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:31 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:54:59 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:00 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:00 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:00 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:01 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:01 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:29 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:29 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:30 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:30 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:30 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:31 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:55:59 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:00 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:00 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:00 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:00 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:00 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:01 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:01 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:29 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:29 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:30 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:30 DEBUG (SyncWorker_7) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:30 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:30 DEBUG (SyncWorker_9) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:30 DEBUG (SyncWorker_10) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:31 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:31 DEBUG (SyncWorker_8) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:56:55 INFO (Recorder) [homeassistant.components.recorder.pool.RecorderPool] Pool recreating
|
457
Config/home-assistant.log.1
Normal file
457
Config/home-assistant.log.1
Normal file
@ -0,0 +1,457 @@
|
||||
2022-04-01 12:28:05 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration vesync which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
|
||||
2022-04-01 12:28:05 INFO (MainThread) [homeassistant.setup] Setup of domain logger took 0.0 seconds
|
||||
2022-04-01 12:28:05 INFO (MainThread) [homeassistant.setup] Setting up recorder
|
||||
2022-04-01 12:28:05 INFO (MainThread) [homeassistant.setup] Setting up system_log
|
||||
2022-04-01 12:28:05 INFO (MainThread) [homeassistant.setup] Setup of domain system_log took 0.0 seconds
|
||||
2022-04-01 12:28:05 WARNING (Recorder) [homeassistant.components.recorder.util] The system could not validate that the sqlite3 database at //home/vlb/temp/HAcore/vesync-bpo/Config/home-assistant_v2.db was shutdown cleanly
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain recorder took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 1: {'lovelace', 'analytics', 'diagnostics', 'image', 'api', 'http', 'websocket_api', 'search', 'config', 'system_log', 'device_automation', 'zeroconf', 'frontend', 'auth', 'dhcp', 'onboarding', 'person', 'webhook', 'ssdp', 'network', 'usb', 'cloud'}
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up lovelace
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up http
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up device_automation
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain device_automation took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up dhcp
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain dhcp took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain lovelace took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain http took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up diagnostics
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up api
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain api took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up websocket_api
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain websocket_api took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up config
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up auth
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain auth took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up webhook
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain webhook took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain diagnostics took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up image
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain config took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up analytics
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up search
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain search took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain image took 0.1 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up network
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain network took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_4) [homeassistant.loader] Loaded google_assistant from homeassistant.components.google_assistant
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up person
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_1) [homeassistant.loader] Loaded alexa from homeassistant.components.alexa
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up usb
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain usb took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain analytics took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_0) [homeassistant.loader] Loaded camera from homeassistant.components.camera
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up zeroconf
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up ssdp
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain ssdp took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain zeroconf took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_4) [homeassistant.loader] Loaded media_player from homeassistant.components.media_player
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up cloud
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain cloud took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain person took 0.3 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up onboarding
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain onboarding took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_0) [homeassistant.loader] Loaded hassio from homeassistant.components.hassio
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_3) [homeassistant.loader] Loaded device_tracker from homeassistant.components.device_tracker
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_1) [homeassistant.loader] Loaded tado from homeassistant.components.tado
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_2) [homeassistant.loader] Loaded group from homeassistant.components.group
|
||||
2022-04-01 12:28:06 INFO (SyncWorker_0) [homeassistant.loader] Loaded panel_custom from homeassistant.components.panel_custom
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up frontend
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain frontend took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.bootstrap] Setting up stage 2: {'logbook', 'input_datetime', 'counter', 'zone', 'script', 'history', 'my', 'mobile_app', 'default_config', 'timer', 'tag', 'media_source', 'input_boolean', 'input_button', 'blueprint', 'system_health', 'automation', 'tts', 'energy', 'vesync', 'map', 'scene', 'input_text', 'radio_browser', 'sun', 'trace', 'input_number', 'input_select'}
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up logbook
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_datetime
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up counter
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up zone
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up history
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain history took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up my
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain my took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up timer
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up tag
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up media_source
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_boolean
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_button
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up blueprint
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain blueprint took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up system_health
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up vesync
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain vesync took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up map
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain map took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up scene
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.components.scene] Setting up scene.homeassistant
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_text
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up radio_browser
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain radio_browser took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up sun
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain sun took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up trace
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain trace took 0.0 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_number
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setting up input_select
|
||||
2022-04-01 12:28:06 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v1/user/login' api
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain logbook took 0.2 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain media_source took 0.2 seconds
|
||||
2022-04-01 12:28:06 INFO (MainThread) [homeassistant.setup] Setup of domain system_health took 0.2 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up energy
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain energy took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain scene took 0.2 seconds
|
||||
2022-04-01 12:28:07 INFO (SyncWorker_0) [homeassistant.loader] Loaded google_translate from homeassistant.components.google_translate
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up script
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up automation
|
||||
2022-04-01 12:28:07 INFO (SyncWorker_3) [homeassistant.loader] Loaded sensor from homeassistant.components.sensor
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up tts
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain script took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain automation took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_datetime took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain counter took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain tag took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain timer took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up sensor
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain sensor took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.components.http] Now listening on port 9443
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain zone took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_boolean took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_button took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_text took 0.3 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.components.sensor] Setting up sensor.energy
|
||||
2022-04-01 12:28:07 INFO (SyncWorker_0) [homeassistant.loader] Loaded notify from homeassistant.components.notify
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_number took 0.2 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain input_select took 0.2 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up mobile_app
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain tts took 0.1 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain mobile_app took 0.1 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up notify
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain notify took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setting up default_config
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.setup] Setup of domain default_config took 0.0 seconds
|
||||
2022-04-01 12:28:07 INFO (MainThread) [homeassistant.components.notify] Setting up notify.mobile_app
|
||||
2022-04-01 12:28:07 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v1/deviceManaged/devices' api
|
||||
2022-04-01 12:28:07 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.vesync] New device list initialized
|
||||
2022-04-01 12:28:07 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:08 INFO (MainThread) [custom_components.vesync.common] 1 VeSync fans found
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.sensor] Setting up sensor.vesync
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_1) [homeassistant.loader] Loaded humidifier from homeassistant.components.humidifier
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_5) [homeassistant.loader] Loaded fan from homeassistant.components.fan
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_4) [homeassistant.loader] Loaded light from homeassistant.components.light
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_3) [homeassistant.loader] Loaded switch from homeassistant.components.switch
|
||||
2022-04-01 12:28:08 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_0) [homeassistant.loader] Loaded number from homeassistant.components.number
|
||||
2022-04-01 12:28:08 INFO (SyncWorker_2) [homeassistant.loader] Loaded binary_sensor from homeassistant.components.binary_sensor
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up humidifier
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain humidifier took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up fan
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain fan took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up light
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up switch
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain switch took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up number
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain number took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setting up binary_sensor
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain binary_sensor took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.humidifier] Setting up humidifier.vesync
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.fan] Setting up fan.vesync
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.switch] Setting up switch.vesync
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.setup] Setup of domain light took 0.0 seconds
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.number] Setting up number.vesync
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.binary_sensor] Setting up binary_sensor.vesync
|
||||
2022-04-01 12:28:08 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:08 INFO (MainThread) [homeassistant.components.light] Setting up light.vesync
|
||||
2022-04-01 12:28:08 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:08 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:08 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:09 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:09 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:09 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:10 INFO (MainThread) [homeassistant.bootstrap] Home Assistant initialized in 5.20s
|
||||
2022-04-01 12:28:10 INFO (MainThread) [homeassistant.core] Starting Home Assistant
|
||||
2022-04-01 12:28:10 INFO (MainThread) [homeassistant.core] Timer:starting
|
||||
2022-04-01 12:28:10 INFO (MainThread) [homeassistant.components.zeroconf] Starting Zeroconf broadcast
|
||||
2022-04-01 12:28:10 INFO (SyncWorker_5) [homeassistant.loader] Loaded somfy from homeassistant.components.somfy
|
||||
2022-04-01 12:28:10 INFO (SyncWorker_0) [homeassistant.loader] Loaded overkiz from homeassistant.components.overkiz
|
||||
2022-04-01 12:28:11 INFO (SyncWorker_5) [homeassistant.loader] Loaded homekit_controller from homeassistant.components.homekit_controller
|
||||
2022-04-01 12:28:11 INFO (SyncWorker_2) [homeassistant.loader] Loaded cast from homeassistant.components.cast
|
||||
2022-04-01 12:28:11 INFO (SyncWorker_3) [homeassistant.loader] Loaded plex from homeassistant.components.plex
|
||||
2022-04-01 12:28:11 INFO (SyncWorker_3) [homeassistant.loader] Loaded hue from homeassistant.components.hue
|
||||
2022-04-01 12:28:12 INFO (SyncWorker_6) [homeassistant.loader] Loaded netatmo from homeassistant.components.netatmo
|
||||
2022-04-01 12:28:12 INFO (SyncWorker_2) [homeassistant.loader] Loaded ipp from homeassistant.components.ipp
|
||||
2022-04-01 12:28:12 INFO (SyncWorker_3) [homeassistant.loader] Loaded harmony from homeassistant.components.harmony
|
||||
2022-04-01 12:28:12 INFO (SyncWorker_6) [homeassistant.loader] Loaded remote from homeassistant.components.remote
|
||||
2022-04-01 12:28:12 INFO (MainThread) [homeassistant.setup] Setting up remote
|
||||
2022-04-01 12:28:12 INFO (MainThread) [homeassistant.setup] Setup of domain remote took 0.0 seconds
|
||||
2022-04-01 12:28:12 INFO (SyncWorker_0) [homeassistant.loader] Loaded upnp from homeassistant.components.upnp
|
||||
2022-04-01 12:28:13 INFO (SyncWorker_2) [homeassistant.loader] Loaded dlna_dms from homeassistant.components.dlna_dms
|
||||
2022-04-01 12:28:13 INFO (SyncWorker_4) [homeassistant.loader] Loaded devolo_home_network from homeassistant.components.devolo_home_network
|
||||
2022-04-01 12:28:13 INFO (SyncWorker_3) [homeassistant.loader] Loaded devolo_home_control from homeassistant.components.devolo_home_control
|
||||
2022-04-01 12:28:13 INFO (SyncWorker_5) [homeassistant.loader] Loaded esphome from homeassistant.components.esphome
|
||||
2022-04-01 12:28:36 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Running websocket_api script
|
||||
2022-04-01 12:28:36 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Executing step call service
|
||||
2022-04-01 12:28:36 INFO (MainThread) [custom_components.vesync.common] 1 VeSync fans found
|
||||
2022-04-01 12:28:36 WARNING (MainThread) [custom_components.vesync.fan] Humidificateur - Unknown device type - LUH-D301S-WEU
|
||||
2022-04-01 12:28:36 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:36 INFO (MainThread) [homeassistant.helpers.entity_registry] Registered new light.vesync entity: light.humidificateur_night_light
|
||||
2022-04-01 12:28:36 ERROR (MainThread) [homeassistant.components.light] Error adding entities for domain light with platform vesync
|
||||
Traceback (most recent call last):
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity_platform.py", line 382, in async_add_entities
|
||||
await asyncio.gather(*tasks)
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity_platform.py", line 614, in _async_add_entity
|
||||
await entity.add_to_platform_finish()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 801, in add_to_platform_finish
|
||||
self.async_write_ha_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 553, in async_write_ha_state
|
||||
self._async_write_ha_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 590, in _async_write_ha_state
|
||||
state = self._stringify_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 559, in _stringify_state
|
||||
if (state := self.state) is None:
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 988, in state
|
||||
if (is_on := self.is_on) is None:
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/Config/custom_components/vesync/light.py", line 234, in is_on
|
||||
return self.smarthumidifier.details["night_light_brightness"] > 0
|
||||
KeyError: 'night_light_brightness'
|
||||
2022-04-01 12:28:36 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved
|
||||
Traceback (most recent call last):
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity_platform.py", line 382, in async_add_entities
|
||||
await asyncio.gather(*tasks)
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity_platform.py", line 614, in _async_add_entity
|
||||
await entity.add_to_platform_finish()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 801, in add_to_platform_finish
|
||||
self.async_write_ha_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 553, in async_write_ha_state
|
||||
self._async_write_ha_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 590, in _async_write_ha_state
|
||||
state = self._stringify_state()
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 559, in _stringify_state
|
||||
if (state := self.state) is None:
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/.venv/lib/python3.9/site-packages/homeassistant/helpers/entity.py", line 988, in state
|
||||
if (is_on := self.is_on) is None:
|
||||
File "/home/vlb/temp/HAcore/vesync-bpo/Config/custom_components/vesync/light.py", line 234, in is_on
|
||||
return self.smarthumidifier.details["night_light_brightness"] > 0
|
||||
KeyError: 'night_light_brightness'
|
||||
2022-04-01 12:28:39 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:41 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:28:42 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:07 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Running websocket_api script
|
||||
2022-04-01 12:29:07 INFO (MainThread) [homeassistant.helpers.script.websocket_api_script] websocket_api script: Executing step call service
|
||||
2022-04-01 12:29:07 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v1/deviceManaged/devices' api
|
||||
2022-04-01 12:29:08 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:09 INFO (MainThread) [custom_components.vesync.common] 1 VeSync fans found
|
||||
2022-04-01 12:29:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:09 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:12 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:39 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:41 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:29:42 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:09 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:09 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:11 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:39 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:41 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:30:42 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:09 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:39 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:41 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:31:42 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:09 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:12 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:39 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:41 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:32:41 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:09 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:39 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:41 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:33:42 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:09 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:39 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:41 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:34:42 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:09 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:39 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:41 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:35:41 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:09 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:12 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:39 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:41 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:36:42 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:09 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:39 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:41 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:37:42 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:09 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:39 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:41 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:41 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:38:41 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:09 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:10 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:11 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:12 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:39 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:40 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:40 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:41 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:41 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:39:42 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:09 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:09 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:10 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:11 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:12 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:39 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:40 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:40 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:40 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:40 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:40 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:41 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:40:41 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:09 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:09 DEBUG (SyncWorker_2) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:10 DEBUG (SyncWorker_0) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:10 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:10 DEBUG (SyncWorker_6) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:10 DEBUG (SyncWorker_4) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:10 DEBUG (SyncWorker_3) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:11 DEBUG (SyncWorker_1) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
||||
2022-04-01 12:41:11 DEBUG (SyncWorker_5) [custom_components.vesync.pyvesync.helpers] [post] calling '/cloud/v2/deviceManaged/bypassV2' api
|
BIN
Config/home-assistant_v2.db
Normal file
BIN
Config/home-assistant_v2.db
Normal file
Binary file not shown.
0
Config/scenes.yaml
Normal file
0
Config/scenes.yaml
Normal file
0
Config/scripts.yaml
Normal file
0
Config/scripts.yaml
Normal file
4
Config/secrets.yaml
Normal file
4
Config/secrets.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
# Use this file to store secrets like usernames and passwords.
|
||||
# Learn more at https://www.home-assistant.io/docs/configuration/secrets/
|
||||
some_password: welcome
|
36
README.md
Normal file
36
README.md
Normal file
@ -0,0 +1,36 @@
|
||||
[](https://github.com/custom-components/hacs)
|
||||
[](https://GitHub.com/vlebourl/vesync-bpo/releases/)
|
||||
|
||||
# VeSync custom component for Home Assistant
|
||||
|
||||
Custom component for Home Assistant to interact with smart devices via the VeSync platform.
|
||||
|
||||
## Installation
|
||||
|
||||
You can install this integration via [HACS](#hacs) or [manually](#manual).
|
||||
This integration will override the core VeSync integration.
|
||||
|
||||
### HACS
|
||||
|
||||
This integration can be installed by adding this repository to HACS, then searching for `VeSync` and choosing install. Reboot Home Assistant and configure the 'VeSync' integration via the integrations page or press the blue button below.
|
||||
|
||||
[](https://my.home-assistant.io/redirect/config_flow_start/?domain=vesync)
|
||||
|
||||
### Manual
|
||||
|
||||
Copy the `custom_components/vesync` to your `custom_components` folder. Reboot Home Assistant and configure the 'Overkiz (by Somfy)' integration via the integrations page or press the blue button below.
|
||||
|
||||
[](https://my.home-assistant.io/redirect/config_flow_start/?domain=vesync)
|
||||
|
||||
### Enable debug logging
|
||||
|
||||
The [logger](https://www.home-assistant.io/integrations/logger/) integration lets you define the level of logging activities in Home Assistant. Turning on debug mode will show more information about unsupported devices in your logbook.
|
||||
|
||||
```yaml
|
||||
logger:
|
||||
default: error
|
||||
logs:
|
||||
custom_components.vesync: debug
|
||||
```
|
||||
|
||||
This integration is heavily based on [VeSync_bpo](https://github.com/borpin/vesync-bpo) and [pyvesync](https://pypi.org/project/pyvesync/)
|
106
custom_components/vesync/__init__.py
Normal file
106
custom_components/vesync/__init__.py
Normal file
@ -0,0 +1,106 @@
|
||||
"""VeSync integration."""
|
||||
import logging
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||
|
||||
from .common import async_process_devices
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
SERVICE_UPDATE_DEVS,
|
||||
VS_BINARY_SENSORS,
|
||||
VS_DISCOVERY,
|
||||
VS_FANS,
|
||||
VS_HUMIDIFIERS,
|
||||
VS_LIGHTS,
|
||||
VS_MANAGER,
|
||||
VS_NUMBERS,
|
||||
VS_SENSORS,
|
||||
VS_SWITCHES,
|
||||
)
|
||||
from .pyvesync.vesync import VeSync
|
||||
|
||||
PLATFORMS = {
|
||||
Platform.SWITCH: VS_SWITCHES,
|
||||
Platform.FAN: VS_FANS,
|
||||
Platform.LIGHT: VS_LIGHTS,
|
||||
Platform.SENSOR: VS_SENSORS,
|
||||
Platform.HUMIDIFIER: VS_HUMIDIFIERS,
|
||||
Platform.NUMBER: VS_NUMBERS,
|
||||
Platform.BINARY_SENSOR: VS_BINARY_SENSORS,
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
|
||||
|
||||
|
||||
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
|
||||
"""Set up Vesync as config entry."""
|
||||
username = config_entry.data[CONF_USERNAME]
|
||||
password = config_entry.data[CONF_PASSWORD]
|
||||
|
||||
time_zone = str(hass.config.time_zone)
|
||||
|
||||
manager = VeSync(username, password, time_zone)
|
||||
|
||||
login = await hass.async_add_executor_job(manager.login)
|
||||
|
||||
if not login:
|
||||
_LOGGER.error("Unable to login to the VeSync server")
|
||||
return False
|
||||
|
||||
device_dict = await async_process_devices(hass, manager)
|
||||
|
||||
forward_setup = hass.config_entries.async_forward_entry_setup
|
||||
|
||||
hass.data[DOMAIN] = {config_entry.entry_id: {}}
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_MANAGER] = manager
|
||||
|
||||
for p, vs_p in PLATFORMS.items():
|
||||
hass.data[DOMAIN][config_entry.entry_id][vs_p] = []
|
||||
if device_dict[VS_SWITCHES]:
|
||||
hass.data[DOMAIN][config_entry.entry_id][vs_p].extend(device_dict[vs_p])
|
||||
hass.async_create_task(forward_setup(config_entry, p))
|
||||
|
||||
async def async_new_device_discovery(service: ServiceCall) -> None:
|
||||
"""Discover if new devices should be added."""
|
||||
manager = hass.data[DOMAIN][config_entry.entry_id][VS_MANAGER]
|
||||
dev_dict = await async_process_devices(hass, manager)
|
||||
|
||||
def _add_new_devices(platform: str) -> None:
|
||||
"""Add new devices to hass."""
|
||||
old_devices = hass.data[DOMAIN][config_entry.entry_id][PLATFORMS[platform]]
|
||||
if new_devices := list(
|
||||
set(dev_dict.get(VS_SWITCHES, [])).difference(old_devices)
|
||||
):
|
||||
old_devices.extend(new_devices)
|
||||
if old_devices:
|
||||
async_dispatcher_send(
|
||||
hass, VS_DISCOVERY.format(PLATFORMS[platform]), new_devices
|
||||
)
|
||||
else:
|
||||
hass.async_create_task(forward_setup(config_entry, platform))
|
||||
|
||||
for k, v in PLATFORMS.items():
|
||||
_add_new_devices(k)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN, SERVICE_UPDATE_DEVS, async_new_device_discovery
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
"""Unload a config entry."""
|
||||
unload_ok = await hass.config_entries.async_unload_platforms(
|
||||
entry, list(PLATFORMS.keys())
|
||||
)
|
||||
if unload_ok:
|
||||
hass.data[DOMAIN].pop(entry.entry_id)
|
||||
|
||||
return unload_ok
|
BIN
custom_components/vesync/__pycache__/__init__.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/__init__.cpython-39.pyc
Normal file
Binary file not shown.
Binary file not shown.
BIN
custom_components/vesync/__pycache__/common.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/common.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/config_flow.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/config_flow.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/const.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/const.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/fan.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/fan.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/humidifier.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/humidifier.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/light.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/light.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/number.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/number.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/sensor.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/sensor.cpython-39.pyc
Normal file
Binary file not shown.
BIN
custom_components/vesync/__pycache__/switch.cpython-39.pyc
Normal file
BIN
custom_components/vesync/__pycache__/switch.cpython-39.pyc
Normal file
Binary file not shown.
103
custom_components/vesync/binary_sensor.py
Normal file
103
custom_components/vesync/binary_sensor.py
Normal file
@ -0,0 +1,103 @@
|
||||
"""Support for power & energy sensors for VeSync outlets."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncBaseEntity, is_humidifier
|
||||
from .const import DOMAIN, VS_BINARY_SENSORS, VS_DISCOVERY
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up binary sensors."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_BINARY_SENSORS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_BINARY_SENSORS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if is_humidifier(dev.device_type):
|
||||
entities.append(VeSyncOutOfWaterSensor(dev))
|
||||
entities.append(VeSyncWaterTankLiftedSensor(dev))
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncHumidifierBinarySensorEntity(VeSyncBaseEntity, BinarySensorEntity):
|
||||
"""Representation of a binary sensor describing diagnostics of a VeSync humidifier."""
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the diagnostic entity category."""
|
||||
return EntityCategory.DIAGNOSTIC
|
||||
|
||||
|
||||
class VeSyncOutOfWaterSensor(VeSyncHumidifierBinarySensorEntity):
|
||||
"""Out of Water Sensor."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return unique ID for out of water sensor on device."""
|
||||
return f"{super().unique_id}-out_of_water"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return sensor name."""
|
||||
return f"{super().name} out of water"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return a value indicating whether the Humidifier is out of water."""
|
||||
return self.smarthumidifier.details["water_lacks"]
|
||||
|
||||
|
||||
class VeSyncWaterTankLiftedSensor(VeSyncHumidifierBinarySensorEntity):
|
||||
"""Tank Lifted Sensor."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return unique ID for water tank lifted sensor on device."""
|
||||
return f"{super().unique_id}-water_tank_lifted"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return sensor name."""
|
||||
return f"{super().name} water tank lifted"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return a value indicating whether the Humidifier's water tank is lifted."""
|
||||
return self.smarthumidifier.details["water_tank_lifted"]
|
140
custom_components/vesync/common.py
Normal file
140
custom_components/vesync/common.py
Normal file
@ -0,0 +1,140 @@
|
||||
"""Common utilities for VeSync Component."""
|
||||
import logging
|
||||
|
||||
from homeassistant.helpers.entity import Entity, ToggleEntity
|
||||
|
||||
from .const import (
|
||||
DOMAIN,
|
||||
VS_BINARY_SENSORS,
|
||||
VS_FANS,
|
||||
VS_HUMIDIFIERS,
|
||||
VS_LIGHTS,
|
||||
VS_NUMBERS,
|
||||
VS_SENSORS,
|
||||
VS_SWITCHES,
|
||||
)
|
||||
from .pyvesync.vesyncfan import model_features
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def is_humidifier(device_type: str) -> bool:
|
||||
"""Return true if the device type is a humidifier."""
|
||||
return model_features(device_type)["module"].find("VeSyncHumid") > -1
|
||||
|
||||
|
||||
async def async_process_devices(hass, manager):
|
||||
"""Assign devices to proper component."""
|
||||
devices = {
|
||||
VS_SWITCHES: [],
|
||||
VS_FANS: [],
|
||||
VS_LIGHTS: [],
|
||||
VS_SENSORS: [],
|
||||
VS_HUMIDIFIERS: [],
|
||||
VS_NUMBERS: [],
|
||||
VS_BINARY_SENSORS: [],
|
||||
}
|
||||
|
||||
await hass.async_add_executor_job(manager.update)
|
||||
|
||||
if manager.fans:
|
||||
for fan in manager.fans:
|
||||
# VeSync classifies humidifiers as fans
|
||||
if is_humidifier(fan.device_type):
|
||||
devices[VS_HUMIDIFIERS].append(fan)
|
||||
devices[VS_NUMBERS].append(fan) # for night light and mist level
|
||||
devices[VS_SWITCHES].append(fan) # for automatic stop and display
|
||||
devices[VS_SENSORS].append(fan) # for humidity sensor
|
||||
devices[VS_BINARY_SENSORS].append(
|
||||
fan
|
||||
) # for out of water and water tank lifted sensors
|
||||
if fan.night_light:
|
||||
devices[VS_LIGHTS].append(fan) # for night light
|
||||
else:
|
||||
devices[VS_FANS].append(fan)
|
||||
_LOGGER.info("%d VeSync fans found", len(manager.fans))
|
||||
|
||||
if manager.bulbs:
|
||||
devices[VS_LIGHTS].extend(manager.bulbs)
|
||||
_LOGGER.info("%d VeSync lights found", len(manager.bulbs))
|
||||
|
||||
if manager.outlets:
|
||||
devices[VS_SWITCHES].extend(manager.outlets)
|
||||
# Expose outlets' power & energy usage as separate sensors
|
||||
devices[VS_SENSORS].extend(manager.outlets)
|
||||
_LOGGER.info("%d VeSync outlets found", len(manager.outlets))
|
||||
|
||||
if manager.switches:
|
||||
for switch in manager.switches:
|
||||
if not switch.is_dimmable():
|
||||
devices[VS_SWITCHES].append(switch)
|
||||
else:
|
||||
devices[VS_LIGHTS].append(switch)
|
||||
_LOGGER.info("%d VeSync switches found", len(manager.switches))
|
||||
|
||||
return devices
|
||||
|
||||
|
||||
class VeSyncBaseEntity(Entity):
|
||||
"""Base class for VeSync Entity Representations."""
|
||||
|
||||
def __init__(self, device):
|
||||
"""Initialize the VeSync device."""
|
||||
self.device = device
|
||||
|
||||
@property
|
||||
def base_unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
if isinstance(self.device.sub_device_no, int):
|
||||
return f"{self.device.cid}{str(self.device.sub_device_no)}"
|
||||
return self.device.cid
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
# The unique_id property may be overridden in subclasses, such as in sensors. Maintaining base_unique_id allows
|
||||
# us to group related entities under a single device.
|
||||
return self.base_unique_id
|
||||
|
||||
@property
|
||||
def base_name(self):
|
||||
"""Return the name of the device."""
|
||||
return self.device.device_name
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the entity (may be overridden)."""
|
||||
return self.base_name
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return True if device is available."""
|
||||
return self.device.connection_status == "online"
|
||||
|
||||
@property
|
||||
def device_info(self):
|
||||
"""Return device information."""
|
||||
return {
|
||||
"identifiers": {(DOMAIN, self.base_unique_id)},
|
||||
"name": self.base_name,
|
||||
"model": self.device.device_type,
|
||||
"default_manufacturer": "VeSync",
|
||||
"sw_version": self.device.current_firm_version,
|
||||
}
|
||||
|
||||
def update(self):
|
||||
"""Update vesync device."""
|
||||
self.device.update()
|
||||
|
||||
|
||||
class VeSyncDevice(VeSyncBaseEntity, ToggleEntity):
|
||||
"""Base class for VeSync Device Representations."""
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if device is on."""
|
||||
return self.device.device_status == "on"
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the device off."""
|
||||
self.device.turn_off()
|
58
custom_components/vesync/config_flow.py
Normal file
58
custom_components/vesync/config_flow.py
Normal file
@ -0,0 +1,58 @@
|
||||
"""Config flow utilities."""
|
||||
from collections import OrderedDict
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
|
||||
from homeassistant.core import callback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .pyvesync.vesync import VeSync
|
||||
|
||||
|
||||
class VeSyncFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow."""
|
||||
|
||||
VERSION = 1
|
||||
|
||||
def __init__(self):
|
||||
"""Instantiate config flow."""
|
||||
self._username = None
|
||||
self._password = None
|
||||
self.data_schema = OrderedDict()
|
||||
self.data_schema[vol.Required(CONF_USERNAME)] = str
|
||||
self.data_schema[vol.Required(CONF_PASSWORD)] = str
|
||||
|
||||
@callback
|
||||
def _show_form(self, errors=None):
|
||||
"""Show form to the user."""
|
||||
return self.async_show_form(
|
||||
step_id="user",
|
||||
data_schema=vol.Schema(self.data_schema),
|
||||
errors=errors or {},
|
||||
)
|
||||
|
||||
async def async_step_user(self, user_input=None):
|
||||
"""Handle a flow start."""
|
||||
if self._async_current_entries():
|
||||
return self.async_abort(reason="single_instance_allowed")
|
||||
|
||||
if not user_input:
|
||||
return self._show_form()
|
||||
|
||||
self._username = user_input[CONF_USERNAME]
|
||||
self._password = user_input[CONF_PASSWORD]
|
||||
|
||||
manager = VeSync(self._username, self._password)
|
||||
login = await self.hass.async_add_executor_job(manager.login)
|
||||
await self.async_set_unique_id(f"{self._username}-{manager.account_id}")
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
if not login:
|
||||
return self._show_form(errors={"base": "invalid_auth"})
|
||||
|
||||
return self.async_create_entry(
|
||||
title=self._username,
|
||||
data={CONF_USERNAME: self._username, CONF_PASSWORD: self._password},
|
||||
)
|
33
custom_components/vesync/const.py
Normal file
33
custom_components/vesync/const.py
Normal file
@ -0,0 +1,33 @@
|
||||
"""Constants for VeSync Component."""
|
||||
|
||||
DOMAIN = "vesync"
|
||||
VS_DISCOVERY = "vesync_discovery_{}"
|
||||
SERVICE_UPDATE_DEVS = "update_devices"
|
||||
|
||||
VS_SWITCHES = "switches"
|
||||
VS_FANS = "fans"
|
||||
VS_LIGHTS = "lights"
|
||||
VS_SENSORS = "sensors"
|
||||
VS_HUMIDIFIERS = "humidifiers"
|
||||
VS_NUMBERS = "numbers"
|
||||
VS_BINARY_SENSORS = "binary_sensors"
|
||||
VS_MANAGER = "manager"
|
||||
|
||||
DEV_TYPE_TO_HA = {
|
||||
"LV-PUR131S": "fan",
|
||||
"Core200S": "fan",
|
||||
"Core300S": "fan",
|
||||
"Core400S": "fan",
|
||||
"Classic300S": "humidifier",
|
||||
"ESD16": "walldimmer",
|
||||
"ESWD16": "walldimmer",
|
||||
"ESL100": "bulb-dimmable",
|
||||
"ESL100CW": "bulb-tunable-white",
|
||||
"wifi-switch-1.3": "outlet",
|
||||
"ESW03-USA": "outlet",
|
||||
"ESW01-EU": "outlet",
|
||||
"ESW15-USA": "outlet",
|
||||
"ESWL01": "switch",
|
||||
"ESWL03": "switch",
|
||||
"ESO15-TB": "outlet",
|
||||
}
|
188
custom_components/vesync/fan.py
Normal file
188
custom_components/vesync/fan.py
Normal file
@ -0,0 +1,188 @@
|
||||
"""Support for VeSync fans."""
|
||||
import logging
|
||||
import math
|
||||
|
||||
from homeassistant.components.fan import SUPPORT_SET_SPEED, FanEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util.percentage import (
|
||||
int_states_in_range,
|
||||
percentage_to_ranged_value,
|
||||
ranged_value_to_percentage,
|
||||
)
|
||||
|
||||
from .common import VeSyncDevice
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_FANS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
FAN_MODE_AUTO = "auto"
|
||||
FAN_MODE_SLEEP = "sleep"
|
||||
# Fixme add other models
|
||||
PRESET_MODES = {
|
||||
"Core200S": [FAN_MODE_SLEEP],
|
||||
"Core300S": [FAN_MODE_AUTO, FAN_MODE_SLEEP],
|
||||
"Core400S": [FAN_MODE_AUTO, FAN_MODE_SLEEP],
|
||||
"LV-PUR131S": [FAN_MODE_AUTO, FAN_MODE_SLEEP],
|
||||
}
|
||||
SPEED_RANGE = (1, 3) # off is not included
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the VeSync fan platform."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_FANS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_FANS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if DEV_TYPE_TO_HA.get(dev.device_type) == "fan":
|
||||
entities.append(VeSyncFanHA(dev))
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
continue
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncFanHA(VeSyncDevice, FanEntity):
|
||||
"""Representation of a VeSync fan."""
|
||||
|
||||
def __init__(self, fan):
|
||||
"""Initialize the VeSync fan device."""
|
||||
super().__init__(fan)
|
||||
self.smartfan = fan
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_SET_SPEED
|
||||
|
||||
@property
|
||||
def percentage(self):
|
||||
"""Return the current speed."""
|
||||
if (
|
||||
self.smartfan.mode == "manual"
|
||||
and (current_level := self.smartfan.fan_level) is not None
|
||||
):
|
||||
return ranged_value_to_percentage(SPEED_RANGE, current_level)
|
||||
return None
|
||||
|
||||
@property
|
||||
def speed_count(self) -> int:
|
||||
"""Return the number of speeds the fan supports."""
|
||||
return int_states_in_range(SPEED_RANGE)
|
||||
|
||||
@property
|
||||
def preset_modes(self):
|
||||
"""Get the list of available preset modes."""
|
||||
return PRESET_MODES[self.device.device_type]
|
||||
|
||||
@property
|
||||
def preset_mode(self):
|
||||
"""Get the current preset mode."""
|
||||
if self.smartfan.mode in (FAN_MODE_AUTO, FAN_MODE_SLEEP):
|
||||
return self.smartfan.mode
|
||||
return None
|
||||
|
||||
@property
|
||||
def unique_info(self):
|
||||
"""Return the ID of this fan."""
|
||||
return self.smartfan.uuid
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes of the fan."""
|
||||
attr = {}
|
||||
|
||||
if hasattr(self.smartfan, "active_time"):
|
||||
attr["active_time"] = self.smartfan.active_time
|
||||
|
||||
if hasattr(self.smartfan, "screen_status"):
|
||||
attr["screen_status"] = self.smartfan.screen_status
|
||||
|
||||
if hasattr(self.smartfan, "child_lock"):
|
||||
attr["child_lock"] = self.smartfan.child_lock
|
||||
|
||||
if hasattr(self.smartfan, "night_light"):
|
||||
attr["night_light"] = self.smartfan.night_light
|
||||
|
||||
if hasattr(self.smartfan, "air_quality"):
|
||||
attr["air_quality"] = self.smartfan.air_quality
|
||||
|
||||
if hasattr(self.smartfan, "mode"):
|
||||
attr["mode"] = self.smartfan.mode
|
||||
|
||||
if hasattr(self.smartfan, "filter_life"):
|
||||
attr["filter_life"] = self.smartfan.filter_life
|
||||
|
||||
return attr
|
||||
|
||||
def set_percentage(self, percentage):
|
||||
"""Set the speed of the device."""
|
||||
if percentage == 0:
|
||||
self.smartfan.turn_off()
|
||||
return
|
||||
|
||||
if not self.smartfan.is_on:
|
||||
self.smartfan.turn_on()
|
||||
|
||||
self.smartfan.manual_mode()
|
||||
self.smartfan.change_fan_speed(
|
||||
math.ceil(percentage_to_ranged_value(SPEED_RANGE, percentage))
|
||||
)
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def set_preset_mode(self, preset_mode):
|
||||
"""Set the preset mode of device."""
|
||||
if preset_mode not in self.preset_modes:
|
||||
raise ValueError(
|
||||
"{preset_mode} is not one of the valid preset modes: {self.preset_modes}"
|
||||
)
|
||||
|
||||
if not self.smartfan.is_on:
|
||||
self.smartfan.turn_on()
|
||||
|
||||
if preset_mode == FAN_MODE_AUTO:
|
||||
self.smartfan.auto_mode()
|
||||
elif preset_mode == FAN_MODE_SLEEP:
|
||||
self.smartfan.sleep_mode()
|
||||
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
speed: str = None,
|
||||
percentage: int = None,
|
||||
preset_mode: str = None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Turn the device on."""
|
||||
if preset_mode:
|
||||
self.set_preset_mode(preset_mode)
|
||||
return
|
||||
if percentage is None:
|
||||
percentage = 50
|
||||
self.set_percentage(percentage)
|
154
custom_components/vesync/humidifier.py
Normal file
154
custom_components/vesync/humidifier.py
Normal file
@ -0,0 +1,154 @@
|
||||
"""Support for VeSync humidifiers."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.humidifier import HumidifierEntity
|
||||
from homeassistant.components.humidifier.const import SUPPORT_MODES
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncDevice, is_humidifier
|
||||
from .const import DOMAIN, VS_DISCOVERY, VS_HUMIDIFIERS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
MAX_HUMIDITY = 80
|
||||
MIN_HUMIDITY = 30
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the VeSync humidifier platform."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_HUMIDIFIERS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_HUMIDIFIERS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if is_humidifier(dev.device_type):
|
||||
entities.append(VeSyncHumidifierHA(dev))
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
continue
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncHumidifierHA(VeSyncDevice, HumidifierEntity):
|
||||
"""Representation of a VeSync humidifier."""
|
||||
|
||||
_attr_max_humidity = MAX_HUMIDITY
|
||||
_attr_min_humidity = MIN_HUMIDITY
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def available_modes(self):
|
||||
"""Return the available mist modes."""
|
||||
return self.device.config_dict["mist_modes"]
|
||||
|
||||
@property
|
||||
def supported_features(self):
|
||||
"""Flag supported features."""
|
||||
return SUPPORT_MODES
|
||||
|
||||
@property
|
||||
def target_humidity(self):
|
||||
"""Return the humidity we try to reach."""
|
||||
return self.smarthumidifier.config["auto_target_humidity"]
|
||||
|
||||
@property
|
||||
def mode(self):
|
||||
"""Get the current preset mode."""
|
||||
if self.smarthumidifier.details["mode"] in self.available_modes:
|
||||
return self.smarthumidifier.details["mode"]
|
||||
return None
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if humidifier is on."""
|
||||
return self.smarthumidifier.enabled # device_status is always on
|
||||
|
||||
@property
|
||||
def unique_info(self):
|
||||
"""Return the ID of this humidifier."""
|
||||
return self.smarthumidifier.uuid
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes of the humidifier."""
|
||||
attr = {}
|
||||
|
||||
if "water_lacks" in self.smarthumidifier.details:
|
||||
attr["water_lacks"] = self.smarthumidifier.details["water_lacks"]
|
||||
|
||||
if "humidity_high" in self.smarthumidifier.details:
|
||||
attr["humidity_high"] = self.smarthumidifier.details["humidity_high"]
|
||||
|
||||
if "water_tank_lifted" in self.smarthumidifier.details:
|
||||
attr["water_tank_lifted"] = self.smarthumidifier.details[
|
||||
"water_tank_lifted"
|
||||
]
|
||||
|
||||
if "automatic_stop_reach_target" in self.smarthumidifier.details:
|
||||
attr["automatic_stop_reach_target"] = self.smarthumidifier.details[
|
||||
"automatic_stop_reach_target"
|
||||
]
|
||||
|
||||
if "mist_level" in self.smarthumidifier.details:
|
||||
attr["mist_level"] = self.smarthumidifier.details["mist_level"]
|
||||
|
||||
return attr
|
||||
|
||||
def set_humidity(self, humidity):
|
||||
"""Set the target humidity of the device."""
|
||||
if humidity not in range(self.min_humidity, self.max_humidity + 1):
|
||||
raise ValueError(
|
||||
"{humidity} is not between {self.min_humidity} and {self.max_humidity} (inclusive)"
|
||||
)
|
||||
self.smarthumidifier.set_humidity(humidity)
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def set_mode(self, mode):
|
||||
"""Set the mode of the device."""
|
||||
if mode not in self.available_modes:
|
||||
raise ValueError(
|
||||
"{mode} is not one of the valid available modes: {self.available_modes}"
|
||||
)
|
||||
if mode == "manual":
|
||||
self.smarthumidifier.set_mist_level(
|
||||
self.smarthumidifier.details["mist_level"]
|
||||
)
|
||||
else:
|
||||
self.smarthumidifier.set_humidity_mode(mode)
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
def turn_on(
|
||||
self,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
"""Turn the device on."""
|
||||
self.smarthumidifier.turn_on()
|
251
custom_components/vesync/light.py
Normal file
251
custom_components/vesync/light.py
Normal file
@ -0,0 +1,251 @@
|
||||
"""Support for VeSync bulbs and wall dimmers."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
ATTR_COLOR_TEMP,
|
||||
COLOR_MODE_BRIGHTNESS,
|
||||
COLOR_MODE_COLOR_TEMP,
|
||||
LightEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncDevice, is_humidifier
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_LIGHTS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up lights."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_LIGHTS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_LIGHTS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if DEV_TYPE_TO_HA.get(dev.device_type) in ("walldimmer", "bulb-dimmable"):
|
||||
entities.append(VeSyncDimmableLightHA(dev))
|
||||
elif DEV_TYPE_TO_HA.get(dev.device_type) in ("bulb-tunable-white",):
|
||||
entities.append(VeSyncTunableWhiteLightHA(dev))
|
||||
elif is_humidifier(dev.device_type):
|
||||
entities.append(VeSyncHumidifierNightLightHA(dev))
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
continue
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
def _vesync_brightness_to_ha(vesync_brightness):
|
||||
try:
|
||||
# check for validity of brightness value received
|
||||
brightness_value = int(vesync_brightness)
|
||||
except ValueError:
|
||||
# deal if any unexpected/non numeric value
|
||||
_LOGGER.debug(
|
||||
"VeSync - received unexpected 'brightness' value from pyvesync api: %s",
|
||||
vesync_brightness,
|
||||
)
|
||||
return 0
|
||||
# convert percent brightness to ha expected range
|
||||
return round((max(1, brightness_value) / 100) * 255)
|
||||
|
||||
|
||||
def _ha_brightness_to_vesync(ha_brightness):
|
||||
# get brightness from HA data
|
||||
brightness = int(ha_brightness)
|
||||
# ensure value between 1-255
|
||||
brightness = max(1, min(brightness, 255))
|
||||
# convert to percent that vesync api expects
|
||||
brightness = round((brightness / 255) * 100)
|
||||
# ensure value between 1-100
|
||||
brightness = max(1, min(brightness, 100))
|
||||
|
||||
return brightness
|
||||
|
||||
|
||||
class VeSyncBaseLight(VeSyncDevice, LightEntity):
|
||||
"""Base class for VeSync Light Devices Representations."""
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Get light brightness."""
|
||||
# get value from pyvesync library api,
|
||||
return _vesync_brightness_to_ha(self.device.brightness)
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
attribute_adjustment_only = False
|
||||
# set white temperature
|
||||
if self.color_mode in (COLOR_MODE_COLOR_TEMP,) and ATTR_COLOR_TEMP in kwargs:
|
||||
# get white temperature from HA data
|
||||
color_temp = int(kwargs[ATTR_COLOR_TEMP])
|
||||
# ensure value between min-max supported Mireds
|
||||
color_temp = max(self.min_mireds, min(color_temp, self.max_mireds))
|
||||
# convert Mireds to Percent value that api expects
|
||||
color_temp = round(
|
||||
((color_temp - self.min_mireds) / (self.max_mireds - self.min_mireds))
|
||||
* 100
|
||||
)
|
||||
# flip cold/warm to what pyvesync api expects
|
||||
color_temp = 100 - color_temp
|
||||
# ensure value between 0-100
|
||||
color_temp = max(0, min(color_temp, 100))
|
||||
# call pyvesync library api method to set color_temp
|
||||
self.device.set_color_temp(color_temp)
|
||||
# flag attribute_adjustment_only, so it doesn't turn_on the device redundantly
|
||||
attribute_adjustment_only = True
|
||||
# set brightness level
|
||||
if (
|
||||
self.color_mode in (COLOR_MODE_BRIGHTNESS, COLOR_MODE_COLOR_TEMP)
|
||||
and ATTR_BRIGHTNESS in kwargs
|
||||
):
|
||||
# get brightness from HA data
|
||||
brightness = _ha_brightness_to_vesync(kwargs[ATTR_BRIGHTNESS])
|
||||
self.device.set_brightness(brightness)
|
||||
# flag attribute_adjustment_only, so it doesn't turn_on the device redundantly
|
||||
attribute_adjustment_only = True
|
||||
# check flag if should skip sending the turn_on command
|
||||
if attribute_adjustment_only:
|
||||
return
|
||||
# send turn_on command to pyvesync api
|
||||
self.device.turn_on()
|
||||
|
||||
|
||||
class VeSyncDimmableLightHA(VeSyncBaseLight, LightEntity):
|
||||
"""Representation of a VeSync dimmable light device."""
|
||||
|
||||
@property
|
||||
def color_mode(self):
|
||||
"""Set color mode for this entity."""
|
||||
return COLOR_MODE_BRIGHTNESS
|
||||
|
||||
@property
|
||||
def supported_color_modes(self):
|
||||
"""Flag supported color_modes (in an array format)."""
|
||||
return [COLOR_MODE_BRIGHTNESS]
|
||||
|
||||
|
||||
class VeSyncTunableWhiteLightHA(VeSyncBaseLight, LightEntity):
|
||||
"""Representation of a VeSync Tunable White Light device."""
|
||||
|
||||
@property
|
||||
def color_temp(self):
|
||||
"""Get device white temperature."""
|
||||
# get value from pyvesync library api,
|
||||
result = self.device.color_temp_pct
|
||||
try:
|
||||
# check for validity of brightness value received
|
||||
color_temp_value = int(result)
|
||||
except ValueError:
|
||||
# deal if any unexpected/non numeric value
|
||||
_LOGGER.debug(
|
||||
"VeSync - received unexpected 'color_temp_pct' value from pyvesync api: %s",
|
||||
result,
|
||||
)
|
||||
return 0
|
||||
# flip cold/warm
|
||||
color_temp_value = 100 - color_temp_value
|
||||
# ensure value between 0-100
|
||||
color_temp_value = max(0, min(color_temp_value, 100))
|
||||
# convert percent value to Mireds
|
||||
color_temp_value = round(
|
||||
self.min_mireds
|
||||
+ ((self.max_mireds - self.min_mireds) / 100 * color_temp_value)
|
||||
)
|
||||
# ensure value between minimum and maximum Mireds
|
||||
return max(self.min_mireds, min(color_temp_value, self.max_mireds))
|
||||
|
||||
@property
|
||||
def min_mireds(self):
|
||||
"""Set device coldest white temperature."""
|
||||
return 154 # 154 Mireds ( 1,000,000 divided by 6500 Kelvin = 154 Mireds)
|
||||
|
||||
@property
|
||||
def max_mireds(self):
|
||||
"""Set device warmest white temperature."""
|
||||
return 370 # 370 Mireds ( 1,000,000 divided by 2700 Kelvin = 370 Mireds)
|
||||
|
||||
@property
|
||||
def color_mode(self):
|
||||
"""Set color mode for this entity."""
|
||||
return COLOR_MODE_COLOR_TEMP
|
||||
|
||||
@property
|
||||
def supported_color_modes(self):
|
||||
"""Flag supported color_modes (in an array format)."""
|
||||
return [COLOR_MODE_COLOR_TEMP]
|
||||
|
||||
|
||||
class VeSyncHumidifierNightLightHA(VeSyncDimmableLightHA):
|
||||
"""Representation of the night light on a VeSync humidifier."""
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
return f"{super().unique_id}-night-light"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return f"{super().name} night light"
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Get night light brightness."""
|
||||
# get value from pyvesync library api,
|
||||
return _vesync_brightness_to_ha(
|
||||
self.smarthumidifier.details["night_light_brightness"]
|
||||
)
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if night light is on."""
|
||||
return self.smarthumidifier.details["night_light_brightness"] > 0
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the configuration entity category."""
|
||||
return EntityCategory.CONFIG
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the night light on."""
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
brightness = _ha_brightness_to_vesync(kwargs[ATTR_BRIGHTNESS])
|
||||
self.smarthumidifier.set_night_light_brightness(brightness)
|
||||
else:
|
||||
self.smarthumidifier.set_night_light_brightness(100)
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the night light off."""
|
||||
self.smarthumidifier.set_night_light_brightness(0)
|
10
custom_components/vesync/manifest.json
Normal file
10
custom_components/vesync/manifest.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"domain": "vesync",
|
||||
"name": "VeSync",
|
||||
"documentation": "https://www.home-assistant.io/integrations/vesync",
|
||||
"codeowners": ["@markperdue", "@webdjoe", "@thegardenmonkey"],
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling",
|
||||
"version": "0.1.2",
|
||||
"issue_tracker": "https://github.com/vlebourl/vesync-bpo"
|
||||
}
|
155
custom_components/vesync/number.py
Normal file
155
custom_components/vesync/number.py
Normal file
@ -0,0 +1,155 @@
|
||||
"""Support for number settings on VeSync devices."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.number import NumberEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncBaseEntity, is_humidifier
|
||||
from .const import DOMAIN, VS_DISCOVERY, VS_NUMBERS
|
||||
|
||||
MAX_HUMIDITY = 80
|
||||
MIN_HUMIDITY = 30
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up numbers."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_NUMBERS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_NUMBERS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if is_humidifier(dev.device_type):
|
||||
entities.extend(
|
||||
(
|
||||
VeSyncHumidifierMistLevelHA(dev),
|
||||
VeSyncHumidifierTargetLevelHA(dev),
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
_LOGGER.debug(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
continue
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncHumidifierNumberEntity(VeSyncBaseEntity, NumberEntity):
|
||||
"""Representation of a number for configuring a VeSync humidifier."""
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the diagnostic entity category."""
|
||||
return EntityCategory.CONFIG
|
||||
|
||||
|
||||
class VeSyncHumidifierMistLevelHA(VeSyncHumidifierNumberEntity):
|
||||
"""Representation of the mist level of a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
return f"{super().unique_id}-mist-level"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return f"{super().name} mist level"
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Return the mist level."""
|
||||
return self.device.details["mist_virtual_level"]
|
||||
|
||||
@property
|
||||
def min_value(self) -> float:
|
||||
"""Return the minimum mist level."""
|
||||
return self.device.config_dict["mist_levels"][0]
|
||||
|
||||
@property
|
||||
def max_value(self) -> float:
|
||||
"""Return the maximum mist level."""
|
||||
return self.device.config_dict["mist_levels"][-1]
|
||||
|
||||
@property
|
||||
def step(self) -> float:
|
||||
"""Return the steps for the mist level."""
|
||||
return 1.0
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes of the humidifier."""
|
||||
return {"mist levels": self.device.config_dict["mist_levels"]}
|
||||
|
||||
def set_value(self, value):
|
||||
"""Set the mist level."""
|
||||
self.device.set_mist_level(int(value))
|
||||
|
||||
|
||||
class VeSyncHumidifierTargetLevelHA(VeSyncHumidifierNumberEntity):
|
||||
"""Representation of the target humidity level of a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
return f"{super().unique_id}-target-level"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return f"{super().name} target level"
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Return the current target humidity level."""
|
||||
return self.device.config["auto_target_humidity"]
|
||||
|
||||
@property
|
||||
def min_value(self) -> float:
|
||||
"""Return the minimum humidity level."""
|
||||
return MIN_HUMIDITY
|
||||
|
||||
@property
|
||||
def max_value(self) -> float:
|
||||
"""Return the maximum humidity level."""
|
||||
return MAX_HUMIDITY
|
||||
|
||||
@property
|
||||
def step(self) -> float:
|
||||
"""Return the humidity change step."""
|
||||
return 1.0
|
||||
|
||||
def set_value(self, value):
|
||||
"""Set the target humidity level."""
|
||||
self.device.set_humidity(int(value))
|
6
custom_components/vesync/pyvesync/__init__.py
Executable file
6
custom_components/vesync/pyvesync/__init__.py
Executable file
@ -0,0 +1,6 @@
|
||||
"""VeSync API Library."""
|
||||
import logging
|
||||
|
||||
logging.basicConfig(
|
||||
level=logging.INFO, format="%(asctime)s - %(levelname)5s - %(message)s"
|
||||
)
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
241
custom_components/vesync/pyvesync/helpers.py
Normal file
241
custom_components/vesync/pyvesync/helpers.py
Normal file
@ -0,0 +1,241 @@
|
||||
"""Helper functions for VeSync API."""
|
||||
|
||||
import hashlib
|
||||
import logging
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
API_BASE_URL = "https://smartapi.vesync.com"
|
||||
API_RATE_LIMIT = 30
|
||||
API_TIMEOUT = 5
|
||||
|
||||
DEFAULT_TZ = "America/New_York"
|
||||
DEFAULT_REGION = "US"
|
||||
|
||||
APP_VERSION = "2.8.6"
|
||||
PHONE_BRAND = "SM N9005"
|
||||
PHONE_OS = "Android"
|
||||
MOBILE_ID = "1234567890123456"
|
||||
USER_TYPE = "1"
|
||||
BYPASS_APP_V = "VeSync 3.0.51"
|
||||
|
||||
|
||||
class Helpers:
|
||||
"""VeSync Helper Functions."""
|
||||
|
||||
@staticmethod
|
||||
def req_headers(manager) -> dict:
|
||||
"""Build header for api requests."""
|
||||
return {
|
||||
"accept-language": "en",
|
||||
"accountId": manager.account_id,
|
||||
"appVersion": APP_VERSION,
|
||||
"content-type": "application/json",
|
||||
"tk": manager.token,
|
||||
"tz": manager.time_zone,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def req_body_base(manager) -> dict:
|
||||
"""Return universal keys for body of api requests."""
|
||||
return {"timeZone": manager.time_zone, "acceptLanguage": "en"}
|
||||
|
||||
@staticmethod
|
||||
def req_body_auth(manager) -> dict:
|
||||
"""Keys for authenticating api requests."""
|
||||
return {"accountID": manager.account_id, "token": manager.token}
|
||||
|
||||
@staticmethod
|
||||
def req_body_details() -> dict:
|
||||
"""Detail keys for api requests."""
|
||||
return {
|
||||
"appVersion": APP_VERSION,
|
||||
"phoneBrand": PHONE_BRAND,
|
||||
"phoneOS": PHONE_OS,
|
||||
"traceId": str(int(time.time())),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def req_body(cls, manager, type_) -> dict:
|
||||
"""Builder for body of api requests."""
|
||||
body = {}
|
||||
|
||||
if type_ == "login":
|
||||
body = {**cls.req_body_base(manager), **cls.req_body_details()}
|
||||
body["email"] = manager.username
|
||||
body["password"] = cls.hash_password(manager.password)
|
||||
body["devToken"] = ""
|
||||
body["userType"] = USER_TYPE
|
||||
body["method"] = "login"
|
||||
elif type_ == "devicedetail":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "devicedetail"
|
||||
body["mobileId"] = MOBILE_ID
|
||||
elif type_ == "devicelist":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "devices"
|
||||
body["pageNo"] = "1"
|
||||
body["pageSize"] = "100"
|
||||
elif type_ == "devicestatus":
|
||||
body = {**cls.req_body_base(manager), **cls.req_body_auth(manager)}
|
||||
elif type_ == "energy_week":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "energyweek"
|
||||
body["mobileId"] = MOBILE_ID
|
||||
elif type_ == "energy_month":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "energymonth"
|
||||
body["mobileId"] = MOBILE_ID
|
||||
elif type_ == "energy_year":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "energyyear"
|
||||
body["mobileId"] = MOBILE_ID
|
||||
elif type_ == "bypass":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "bypass"
|
||||
elif type_ == "bypass_config":
|
||||
body = {
|
||||
**cls.req_body_base(manager),
|
||||
**cls.req_body_auth(manager),
|
||||
**cls.req_body_details(),
|
||||
}
|
||||
body["method"] = "firmwareUpdateInfo"
|
||||
|
||||
return body
|
||||
|
||||
@staticmethod
|
||||
def calculate_hex(hex_string) -> float:
|
||||
"""Credit for conversion to itsnotlupus/vesync_wsproxy."""
|
||||
hex_conv = hex_string.split(":")
|
||||
return (int(hex_conv[0], 16) + int(hex_conv[1], 16)) / 8192
|
||||
|
||||
@staticmethod
|
||||
def hash_password(string) -> str:
|
||||
"""Encode password."""
|
||||
return hashlib.md5(string.encode("utf-8")).hexdigest()
|
||||
|
||||
@staticmethod
|
||||
def call_api(
|
||||
api: str, method: str, json: dict = None, headers: dict = None
|
||||
) -> tuple:
|
||||
"""Make API calls by passing endpoint, header and body."""
|
||||
response = None
|
||||
status_code = None
|
||||
|
||||
try:
|
||||
logger.debug("[%s] calling '%s' api", method, api)
|
||||
if method.lower() == "get":
|
||||
r = requests.get(
|
||||
API_BASE_URL + api, json=json, headers=headers, timeout=API_TIMEOUT
|
||||
)
|
||||
elif method.lower() == "post":
|
||||
r = requests.post(
|
||||
API_BASE_URL + api, json=json, headers=headers, timeout=API_TIMEOUT
|
||||
)
|
||||
elif method.lower() == "put":
|
||||
r = requests.put(
|
||||
API_BASE_URL + api, json=json, headers=headers, timeout=API_TIMEOUT
|
||||
)
|
||||
except requests.exceptions.RequestException as e:
|
||||
logger.debug(e)
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
else:
|
||||
if r.status_code == 200:
|
||||
status_code = 200
|
||||
if r.content:
|
||||
response = r.json()
|
||||
else:
|
||||
logger.debug("Unable to fetch %s%s", API_BASE_URL, api)
|
||||
return response, status_code
|
||||
|
||||
@staticmethod
|
||||
def code_check(r: dict) -> bool:
|
||||
"""Test if code == 0 for successful API call."""
|
||||
return isinstance(r, dict) and r.get("code") == 0
|
||||
|
||||
@staticmethod
|
||||
def build_details_dict(r: dict) -> dict:
|
||||
"""Build details dictionary from API response."""
|
||||
return {
|
||||
"active_time": r.get("activeTime", 0),
|
||||
"energy": r.get("energy", 0),
|
||||
"night_light_status": r.get("nightLightStatus", None),
|
||||
"night_light_brightness": r.get("nightLightBrightness", None),
|
||||
"night_light_automode": r.get("nightLightAutomode", None),
|
||||
"power": r.get("power", 0),
|
||||
"voltage": r.get("voltage", 0),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def build_energy_dict(r: dict) -> dict:
|
||||
"""Build energy dictionary from API response."""
|
||||
return {
|
||||
"energy_consumption_of_today": r.get("energyConsumptionOfToday", 0),
|
||||
"cost_per_kwh": r.get("costPerKWH", 0),
|
||||
"max_energy": r.get("maxEnergy", 0),
|
||||
"total_energy": r.get("totalEnergy", 0),
|
||||
"currency": r.get("currency", 0),
|
||||
"data": r.get("data", 0),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def build_config_dict(r: dict) -> dict:
|
||||
"""Build configuration dictionary from API response."""
|
||||
if r.get("threshold") is not None:
|
||||
threshold = r.get("threshold")
|
||||
else:
|
||||
threshold = r.get("thresHold")
|
||||
return {
|
||||
"current_firmware_version": r.get("currentFirmVersion"),
|
||||
"latest_firmware_version": r.get("latestFirmVersion"),
|
||||
"maxPower": r.get("maxPower"),
|
||||
"threshold": threshold,
|
||||
"power_protection": r.get("powerProtectionStatus"),
|
||||
"energy_saving_status": r.get("energySavingStatus"),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def bypass_body_v2(cls, manager):
|
||||
"""Build body dict for bypass calls."""
|
||||
bdy = {}
|
||||
bdy.update(**cls.req_body(manager, "bypass"))
|
||||
bdy["method"] = "bypassV2"
|
||||
bdy["debugMode"] = False
|
||||
bdy["deviceRegion"] = DEFAULT_REGION
|
||||
return bdy
|
||||
|
||||
@staticmethod
|
||||
def bypass_header():
|
||||
"""Build bypass header dict."""
|
||||
return {
|
||||
"Content-Type": "application/json; charset=UTF-8",
|
||||
"User-Agent": "okhttp/3.12.1",
|
||||
}
|
302
custom_components/vesync/pyvesync/vesync.py
Executable file
302
custom_components/vesync/pyvesync/vesync.py
Executable file
@ -0,0 +1,302 @@
|
||||
"""VeSync API Device Library."""
|
||||
|
||||
from itertools import chain
|
||||
import logging
|
||||
import re
|
||||
import time
|
||||
from typing import Tuple
|
||||
|
||||
from . import (
|
||||
vesyncbulb as bulb_mods,
|
||||
vesyncfan as fan_mods,
|
||||
vesyncoutlet as outlet_mods,
|
||||
vesyncswitch as switch_mods,
|
||||
)
|
||||
from .helpers import Helpers
|
||||
from .vesyncbasedevice import VeSyncBaseDevice
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
API_RATE_LIMIT: int = 30
|
||||
DEFAULT_TZ: str = "America/New_York"
|
||||
|
||||
DEFAULT_ENER_UP_INT: int = 21600
|
||||
|
||||
|
||||
def object_factory(dev_type, config, manager) -> Tuple[str, VeSyncBaseDevice]:
|
||||
"""Get device type and instantiate class."""
|
||||
|
||||
def fans(dev_type, config, manager):
|
||||
fan_cls = fan_mods.fan_modules[dev_type]
|
||||
fan_obj = getattr(fan_mods, fan_cls)
|
||||
return "fans", fan_obj(config, manager)
|
||||
|
||||
def outlets(dev_type, config, manager):
|
||||
outlet_cls = outlet_mods.outlet_modules[dev_type]
|
||||
outlet_obj = getattr(outlet_mods, outlet_cls)
|
||||
return "outlets", outlet_obj(config, manager)
|
||||
|
||||
def switches(dev_type, config, manager):
|
||||
switch_cls = switch_mods.switch_modules[dev_type]
|
||||
switch_obj = getattr(switch_mods, switch_cls)
|
||||
return "switches", switch_obj(config, manager)
|
||||
|
||||
def bulbs(dev_type, config, manager):
|
||||
bulb_cls = bulb_mods.bulb_modules[dev_type]
|
||||
bulb_obj = getattr(bulb_mods, bulb_cls)
|
||||
return "bulbs", bulb_obj(config, manager)
|
||||
|
||||
if dev_type in fan_mods.fan_modules:
|
||||
type_str, dev_obj = fans(dev_type, config, manager)
|
||||
elif dev_type in outlet_mods.outlet_modules:
|
||||
type_str, dev_obj = outlets(dev_type, config, manager)
|
||||
elif dev_type in switch_mods.switch_modules:
|
||||
type_str, dev_obj = switches(dev_type, config, manager)
|
||||
elif dev_type in bulb_mods.bulb_modules:
|
||||
type_str, dev_obj = bulbs(dev_type, config, manager)
|
||||
else:
|
||||
logger.debug(
|
||||
"Unknown device named %s model %s",
|
||||
config.get("deviceName", ""),
|
||||
config.get("deviceType", ""),
|
||||
)
|
||||
type_str = "unknown"
|
||||
dev_obj = None
|
||||
return type_str, dev_obj
|
||||
|
||||
|
||||
class VeSync:
|
||||
"""VeSync API functions."""
|
||||
|
||||
def __init__(self, username, password, time_zone=DEFAULT_TZ, debug=False):
|
||||
"""Initialize VeSync class with username, password and time zone."""
|
||||
self.debug = debug
|
||||
if debug:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
self.username = username
|
||||
self.password = password
|
||||
self.token = None
|
||||
self.account_id = None
|
||||
self.devices = None
|
||||
self.enabled = False
|
||||
self.update_interval = API_RATE_LIMIT
|
||||
self.last_update_ts = None
|
||||
self.in_process = False
|
||||
self._energy_update_interval = DEFAULT_ENER_UP_INT
|
||||
self._energy_check = True
|
||||
self._dev_list = {}
|
||||
self.outlets = []
|
||||
self.switches = []
|
||||
self.fans = []
|
||||
self.bulbs = []
|
||||
self.scales = []
|
||||
|
||||
self._dev_list = {
|
||||
"fans": self.fans,
|
||||
"outlets": self.outlets,
|
||||
"switches": self.switches,
|
||||
"bulbs": self.bulbs,
|
||||
}
|
||||
|
||||
if isinstance(time_zone, str) and time_zone:
|
||||
reg_test = r"[^a-zA-Z/_]"
|
||||
if bool(re.search(reg_test, time_zone)):
|
||||
self.time_zone = DEFAULT_TZ
|
||||
logger.debug("Invalid characters in time zone - %s", time_zone)
|
||||
else:
|
||||
self.time_zone = time_zone
|
||||
else:
|
||||
self.time_zone = DEFAULT_TZ
|
||||
logger.debug("Time zone is not a string")
|
||||
|
||||
@property
|
||||
def energy_update_interval(self) -> int:
|
||||
"""Return energy update interval."""
|
||||
return self._energy_update_interval
|
||||
|
||||
@energy_update_interval.setter
|
||||
def energy_update_interval(self, new_energy_update: int) -> None:
|
||||
"""Set energy update interval in seconds."""
|
||||
if new_energy_update > 0:
|
||||
self._energy_update_interval = new_energy_update
|
||||
|
||||
@staticmethod
|
||||
def remove_dev_test(device, new_list: list) -> bool:
|
||||
"""Test if device should be removed - False = Remove."""
|
||||
if isinstance(new_list, list) and device.cid:
|
||||
for item in new_list:
|
||||
device_found = False
|
||||
if "cid" in item:
|
||||
if device.cid == item["cid"]:
|
||||
device_found = True
|
||||
break
|
||||
else:
|
||||
logger.debug("No cid found in - %s", str(item))
|
||||
if not device_found:
|
||||
logger.debug(
|
||||
"Device removed - %s - %s", device.device_name, device.device_type
|
||||
)
|
||||
return False
|
||||
return True
|
||||
|
||||
def add_dev_test(self, new_dev: dict) -> bool:
|
||||
"""Test if new device should be added - True = Add."""
|
||||
if "cid" in new_dev:
|
||||
for _, v in self._dev_list.items():
|
||||
for dev in v:
|
||||
if (
|
||||
dev.cid == new_dev.get("cid")
|
||||
and new_dev.get("subDeviceNo", 0) == dev.sub_device_no
|
||||
):
|
||||
return False
|
||||
return True
|
||||
|
||||
def remove_old_devices(self, devices: list) -> bool:
|
||||
"""Remove devices not found in device list return."""
|
||||
for k, v in self._dev_list.items():
|
||||
before = len(v)
|
||||
v[:] = [x for x in v if self.remove_dev_test(x, devices)]
|
||||
after = len(v)
|
||||
if before != after:
|
||||
logger.debug("%s %s removed", str(before - after), k)
|
||||
return True
|
||||
|
||||
@staticmethod
|
||||
def set_dev_id(devices: list) -> list:
|
||||
"""Correct devices without cid or uuid."""
|
||||
dev_rem = []
|
||||
for dev_num, dev in enumerate(devices):
|
||||
if dev.get("cid") is None:
|
||||
if dev.get("macID") is not None:
|
||||
dev["cid"] = dev["macID"]
|
||||
elif dev.get("uuid") is not None:
|
||||
dev["cid"] = dev["uuid"]
|
||||
else:
|
||||
dev_rem.append(dev_num)
|
||||
logger.warning("Device with no ID - %s", dev.get("deviceName"))
|
||||
if dev_rem:
|
||||
devices = [i for j, i in enumerate(devices) if j not in dev_rem]
|
||||
return devices
|
||||
|
||||
def process_devices(self, dev_list: list) -> bool:
|
||||
"""Instantiate Device Objects."""
|
||||
devices = VeSync.set_dev_id(dev_list)
|
||||
|
||||
num_devices = sum(
|
||||
len(v) if isinstance(v, list) else 1 for _, v in self._dev_list.items()
|
||||
)
|
||||
|
||||
if not devices:
|
||||
logger.warning("No devices found in api return")
|
||||
return False
|
||||
if num_devices == 0:
|
||||
logger.debug("New device list initialized")
|
||||
else:
|
||||
self.remove_old_devices(devices)
|
||||
|
||||
devices[:] = [x for x in devices if self.add_dev_test(x)]
|
||||
|
||||
detail_keys = ["deviceType", "deviceName", "deviceStatus"]
|
||||
for dev in devices:
|
||||
if any(k not in dev for k in detail_keys):
|
||||
logger.debug("Error adding device")
|
||||
continue
|
||||
dev_type = dev.get("deviceType")
|
||||
try:
|
||||
device_str, device_obj = object_factory(dev_type, dev, self)
|
||||
device_list = getattr(self, device_str)
|
||||
device_list.append(device_obj)
|
||||
except AttributeError as err:
|
||||
logger.debug("Error - %s", err)
|
||||
logger.debug("%s device not added", dev_type)
|
||||
continue
|
||||
|
||||
return True
|
||||
|
||||
def get_devices(self) -> bool:
|
||||
"""Return tuple listing outlets, switches, and fans of devices."""
|
||||
if not self.enabled:
|
||||
return False
|
||||
|
||||
self.in_process = True
|
||||
proc_return = False
|
||||
response, _ = Helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/devices",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self),
|
||||
json=Helpers.req_body(self, "devicelist"),
|
||||
)
|
||||
|
||||
if response and Helpers.code_check(response):
|
||||
if "result" in response and "list" in response["result"]:
|
||||
device_list = response["result"]["list"]
|
||||
if self.debug:
|
||||
logger.debug(str(device_list))
|
||||
proc_return = self.process_devices(device_list)
|
||||
else:
|
||||
logger.error("Device list in response not found")
|
||||
else:
|
||||
logger.warning("Error retrieving device list")
|
||||
|
||||
self.in_process = False
|
||||
|
||||
return proc_return
|
||||
|
||||
def login(self) -> bool:
|
||||
"""Return True if log in request succeeds."""
|
||||
user_check = isinstance(self.username, str) and len(self.username) > 0
|
||||
pass_check = isinstance(self.password, str) and len(self.password) > 0
|
||||
if not user_check:
|
||||
logger.error("Username invalid")
|
||||
return False
|
||||
if not pass_check:
|
||||
logger.error("Password invalid")
|
||||
return False
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/cloud/v1/user/login", "post", json=Helpers.req_body(self, "login")
|
||||
)
|
||||
|
||||
if Helpers.code_check(response) and "result" in response:
|
||||
self.token = response.get("result").get("token")
|
||||
self.account_id = response.get("result").get("accountID")
|
||||
self.enabled = True
|
||||
|
||||
return True
|
||||
logger.error("Error logging in with username and password")
|
||||
return False
|
||||
|
||||
def device_time_check(self) -> bool:
|
||||
"""Test if update interval has been exceeded."""
|
||||
return (
|
||||
self.last_update_ts is None
|
||||
or (time.time() - self.last_update_ts) > self.update_interval
|
||||
)
|
||||
|
||||
def update(self) -> None:
|
||||
"""Fetch updated information about devices."""
|
||||
if self.device_time_check():
|
||||
|
||||
if not self.enabled:
|
||||
logger.error("Not logged in to VeSync")
|
||||
return
|
||||
self.get_devices()
|
||||
|
||||
devices = list(self._dev_list.values())
|
||||
|
||||
for device in chain(*devices):
|
||||
device.update()
|
||||
|
||||
self.last_update_ts = time.time()
|
||||
|
||||
def update_energy(self, bypass_check=False) -> None:
|
||||
"""Fetch updated energy information about devices."""
|
||||
if self.outlets:
|
||||
for outlet in self.outlets:
|
||||
outlet.update_energy(bypass_check)
|
||||
|
||||
def update_all_devices(self) -> None:
|
||||
"""Run get_details() for each device."""
|
||||
devices = list(self._dev_list.keys())
|
||||
for dev in chain(*devices):
|
||||
dev.get_details()
|
117
custom_components/vesync/pyvesync/vesyncbasedevice.py
Normal file
117
custom_components/vesync/pyvesync/vesyncbasedevice.py
Normal file
@ -0,0 +1,117 @@
|
||||
"""Base class for all VeSync devices."""
|
||||
|
||||
import collections
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional, Union
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VeSyncBaseDevice:
|
||||
"""Properties shared across all VeSync devices."""
|
||||
|
||||
def __init__(self, details: dict, manager):
|
||||
"""Initialize VeSync device base class."""
|
||||
self.manager = manager
|
||||
if "cid" in details and details["cid"] is not None:
|
||||
self.device_name: str = details.get("deviceName", None)
|
||||
self.device_image: Optional[str] = details.get("deviceImg", None)
|
||||
self.cid: str = details.get("cid", None)
|
||||
self.connection_status: str = details.get("connectionStatus", None)
|
||||
self.connection_type: Optional[str] = details.get("connectionType", None)
|
||||
self.device_type: str = details.get("deviceType", None)
|
||||
self.type: str = details.get("type", None)
|
||||
self.uuid: Optional[str] = details.get("uuid", None)
|
||||
self.config_module: str = details.get("configModule", None)
|
||||
self.mac_id: Optional[str] = details.get("macID", None)
|
||||
self.mode: Optional[str] = details.get("mode", None)
|
||||
self.speed: Union[str, int, None] = details.get("speed", None)
|
||||
self.extension = details.get("extension", None)
|
||||
self.current_firm_version = details.get("currentFirmVersion", None)
|
||||
self.sub_device_no = details.get("subDeviceNo", 0)
|
||||
self.config: dict = {}
|
||||
if isinstance(details.get("extension"), dict):
|
||||
ext = details["extension"]
|
||||
self.speed = ext.get("fanSpeedLevel")
|
||||
self.mode = ext.get("mode")
|
||||
if self.connection_status != "online":
|
||||
self.device_status = "off"
|
||||
else:
|
||||
self.device_status = details.get("deviceStatus", None)
|
||||
|
||||
else:
|
||||
logger.error("No cid found for %s", self.__class__.__name__)
|
||||
|
||||
def __eq__(self, other):
|
||||
"""Use device CID and subdevice number to test equality."""
|
||||
return bool(other.cid == self.cid and other.sub_device_no == self.sub_device_no)
|
||||
|
||||
def __hash__(self):
|
||||
"""Use CID and sub-device number to make device hash."""
|
||||
if isinstance(self.sub_device_no, int) and self.sub_device_no > 0:
|
||||
return hash(self.cid + str(self.sub_device_no))
|
||||
return hash(self.cid)
|
||||
|
||||
def __str__(self):
|
||||
"""Use device info for string represtation of class."""
|
||||
return f"Device Name: {self.device_name}, \
|
||||
Device Type: {self.device_type},\
|
||||
SubDevice No.: {self.sub_device_no},\
|
||||
Status: {self.device_status}"
|
||||
|
||||
def __repr__(self):
|
||||
"""Representation of device details."""
|
||||
return f"DevClass: {self.__class__.__name__},\
|
||||
Name:{self.device_name}, Device No: {self.sub_device_no},\
|
||||
DevStatus: {self.device_status}, CID: {self.cid}"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if device is on."""
|
||||
if self.device_status == "on":
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def firmware_update(self) -> bool:
|
||||
"""Return True if firmware update available."""
|
||||
cfv = self.config.get("current_firmware_version")
|
||||
lfv = self.config.get("latest_firmware_version")
|
||||
if cfv is not None and lfv is not None:
|
||||
if cfv != lfv:
|
||||
return True
|
||||
else:
|
||||
logger.debug("Call device.get_config() to get firmware versions")
|
||||
return False
|
||||
|
||||
def display(self) -> None:
|
||||
"""Print formatted device info to stdout."""
|
||||
disp = [
|
||||
("Device Name:", self.device_name),
|
||||
("Model: ", self.device_type),
|
||||
("Subdevice No: ", str(self.sub_device_no)),
|
||||
("Status: ", self.device_status),
|
||||
("Online: ", self.connection_status),
|
||||
("Type: ", self.type),
|
||||
("CID: ", self.cid),
|
||||
]
|
||||
if self.uuid is not None:
|
||||
disp.append(("UUID: ", self.uuid))
|
||||
disp1 = collections.OrderedDict(disp)
|
||||
for k, v in disp1.items():
|
||||
print(f"{k:.<15} {v:<15}")
|
||||
|
||||
def displayJSON(self) -> str:
|
||||
"""JSON API for device details."""
|
||||
return json.dumps(
|
||||
{
|
||||
"Device Name": self.device_name,
|
||||
"Model": self.device_type,
|
||||
"Subdevice No": str(self.sub_device_no),
|
||||
"Status": self.device_status,
|
||||
"Online": self.connection_status,
|
||||
"Type": self.type,
|
||||
"CID": self.cid,
|
||||
}
|
||||
)
|
378
custom_components/vesync/pyvesync/vesyncbulb.py
Normal file
378
custom_components/vesync/pyvesync/vesyncbulb.py
Normal file
@ -0,0 +1,378 @@
|
||||
"""Etekcity Smart Light Bulb."""
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, Union
|
||||
|
||||
from .helpers import Helpers as helpers
|
||||
from .vesyncbasedevice import VeSyncBaseDevice
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# Possible features - dimmable, color_temp, rgb_shift
|
||||
feature_dict: dict = {
|
||||
"ESL100": {"module": "VeSyncBulbESL100", "features": ["dimmable"]},
|
||||
"ESL100CW": {
|
||||
"module": "VeSyncBulbESL100CW",
|
||||
"features": ["dimmable", "color_temp"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
bulb_modules: dict = {k: v["module"] for k, v in feature_dict.items()}
|
||||
|
||||
__all__: list = list(bulb_modules.values()) + ["bulb_modules"]
|
||||
|
||||
|
||||
def pct_to_kelvin(pct: float, max_k: int = 6500, min_k: int = 2700) -> float:
|
||||
"""Convert percent to kelvin."""
|
||||
return ((max_k - min_k) * pct / 100) + min_k
|
||||
|
||||
|
||||
class VeSyncBulb(VeSyncBaseDevice):
|
||||
"""Base class for VeSync Bulbs."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, details: Dict[str, Union[str, list]], manager):
|
||||
"""Initialize VeSync smart bulb base class."""
|
||||
super().__init__(details, manager)
|
||||
self._brightness = 0
|
||||
self._color_temp = 0
|
||||
self.features = feature_dict.get(self.device_type, {}).get("features")
|
||||
if self.features is None:
|
||||
logger.error("No configuration set for - %s", self.device_name)
|
||||
raise RuntimeError(f"No configuration set for - {self.device_name}")
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
"""Return brightness of vesync bulb."""
|
||||
if self.dimmable_feature and self._brightness is not None:
|
||||
return self._brightness
|
||||
return 0
|
||||
|
||||
@property
|
||||
def color_temp_kelvin(self) -> int:
|
||||
"""Return Color Temp of bulb if supported in Kelvin."""
|
||||
if self.color_temp_feature and self._color_temp is not None:
|
||||
return int(pct_to_kelvin(self._color_temp))
|
||||
return 0
|
||||
|
||||
@property
|
||||
def color_temp_pct(self) -> int:
|
||||
"""Return color temperature of bulb in percent."""
|
||||
if self.color_temp_feature and self._color_temp is not None:
|
||||
return int(self._color_temp)
|
||||
return 0
|
||||
|
||||
@property
|
||||
def dimmable_feature(self) -> bool:
|
||||
"""Return true if dimmable bulb."""
|
||||
return "dimmable" in self.features
|
||||
|
||||
@property
|
||||
def color_temp_feature(self) -> bool:
|
||||
"""Return true if bulb supports color temperature changes."""
|
||||
return "color_temp" in feature_dict[self.device_type]
|
||||
|
||||
@property
|
||||
def rgb_shift_feature(self) -> bool:
|
||||
"""Return True if bulb supports changing color."""
|
||||
return "rgb_shift" in feature_dict[self.device_type]
|
||||
|
||||
@abstractmethod
|
||||
def get_details(self) -> None:
|
||||
"""Get vesync bulb details."""
|
||||
|
||||
@abstractmethod
|
||||
def toggle(self, status: str) -> bool:
|
||||
"""Toggle vesync lightbulb."""
|
||||
|
||||
@abstractmethod
|
||||
def get_config(self) -> None:
|
||||
"""Call api to get configuration details and firmware."""
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn on vesync bulbs."""
|
||||
return self._toggle("on")
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn off vesync bulbs."""
|
||||
return self._toggle("off")
|
||||
|
||||
def _toggle(self, state: str, warning: str):
|
||||
if self.toggle(state):
|
||||
self.device_status = state
|
||||
return True
|
||||
logger.warning("Error turning %s %s", self.device_name, state)
|
||||
return False
|
||||
|
||||
def update(self) -> None:
|
||||
"""Update bulb details."""
|
||||
self.get_details()
|
||||
|
||||
def display(self) -> None:
|
||||
"""Return formatted bulb info to stdout."""
|
||||
super().display()
|
||||
if self.connection_status == "online" and self.dimmable_feature:
|
||||
disp1 = [("Brightness: ", self.brightness, "%")]
|
||||
for line in disp1:
|
||||
print(f"{line[0]:.<17} {line[1]} {line[2]}")
|
||||
|
||||
def displayJSON(self) -> str:
|
||||
"""Return bulb device info in JSON format."""
|
||||
sup = super().displayJSON()
|
||||
sup_val = json.loads(sup)
|
||||
if self.connection_status == "online":
|
||||
if self.dimmable_feature:
|
||||
sup_val.update({"Brightness": str(self.brightness)})
|
||||
if self.color_temp_feature:
|
||||
sup_val.update({"Kelvin": str(self.color_temp_kelvin)})
|
||||
return sup_val
|
||||
|
||||
|
||||
class VeSyncBulbESL100(VeSyncBulb):
|
||||
"""Object to hold VeSync ESL100 light bulb."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize Etekcity ESL100 Dimmable Bulb."""
|
||||
super().__init__(details, manager)
|
||||
self.details: dict = {}
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get details of dimmable bulb."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
r, _ = helpers.call_api(
|
||||
"/SmartBulb/v1/device/devicedetail",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
if helpers.code_check(r):
|
||||
self.connection_status = r.get("connectionStatus")
|
||||
self.device_status = r.get("deviceStatus")
|
||||
if self.dimmable_feature:
|
||||
self._brightness = int(r.get("brightNess"))
|
||||
else:
|
||||
logger.debug("Error getting %s details", self.device_name)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get configuration of dimmable bulb."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/SmartBulb/v1/device/configurations",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self.config = helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.warning("Error getting %s config info", self.device_name)
|
||||
|
||||
def toggle(self, status) -> bool:
|
||||
"""Toggle dimmable bulb."""
|
||||
body = self._get_body(status)
|
||||
r, _ = helpers.call_api(
|
||||
"/SmartBulb/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
if helpers.code_check(r):
|
||||
self.device_status = status
|
||||
return True
|
||||
return False
|
||||
|
||||
def set_brightness(self, brightness: int) -> bool:
|
||||
"""Set brightness of dimmable bulb."""
|
||||
if not self.dimmable_feature:
|
||||
logger.debug("%s is not dimmable", self.device_name)
|
||||
return False
|
||||
if isinstance(brightness, int) and (brightness <= 0 or brightness > 100):
|
||||
|
||||
logger.warning("Invalid brightness")
|
||||
return False
|
||||
|
||||
body = self._get_body("on")
|
||||
body["brightNess"] = str(brightness)
|
||||
r, _ = helpers.call_api(
|
||||
"/SmartBulb/v1/device/updateBrightness",
|
||||
"put",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self._brightness = brightness
|
||||
return True
|
||||
|
||||
logger.debug("Error setting brightness for %s", self.device_name)
|
||||
return False
|
||||
|
||||
def _get_body(self, status: str):
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = status
|
||||
return body
|
||||
|
||||
|
||||
class VeSyncBulbESL100CW(VeSyncBulb):
|
||||
"""VeSync Tunable and Dimmable White Bulb."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize Etekcity Tunable white bulb."""
|
||||
super().__init__(details, manager)
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get details of tunable bulb."""
|
||||
body = helpers.req_body(self.manager, "bypass")
|
||||
body["cid"] = self.cid
|
||||
body["jsonCmd"] = {"getLightStatus": "get"}
|
||||
body["configModule"] = self.config_module
|
||||
r, _ = helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/bypass",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
if not isinstance(r, dict) or not helpers.code_check(r):
|
||||
logger.debug("Error calling %s", self.device_name)
|
||||
return
|
||||
response = r
|
||||
if response.get("result", {}).get("light") is not None:
|
||||
light = response.get("result", {}).get("light")
|
||||
self.connection_status = "online"
|
||||
self.device_status = light.get("action", "off")
|
||||
if self.dimmable_feature:
|
||||
self._brightness = light.get("brightness")
|
||||
if self.color_temp_feature:
|
||||
self._color_temp = light.get("colorTempe")
|
||||
elif response.get("code") == -11300027:
|
||||
logger.debug("%s device offline", self.device_name)
|
||||
self.connection_status = "offline"
|
||||
self.device_status = "off"
|
||||
else:
|
||||
logger.debug(
|
||||
"%s - Unknown return code - %d with message %s",
|
||||
self.device_name,
|
||||
response.get("code"),
|
||||
response.get("msg"),
|
||||
)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get configuration and firmware info of tunable bulb."""
|
||||
body = helpers.req_body(self.manager, "bypass_config")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/configurations",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self.config = helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.debug("Error getting %s config info", self.device_name)
|
||||
|
||||
def toggle(self, status) -> bool:
|
||||
"""Toggle tunable bulb."""
|
||||
body = helpers.req_body(self.manager, "bypass")
|
||||
body["cid"] = self.cid
|
||||
body["configModule"] = self.config_module
|
||||
body["jsonCmd"] = {"light": {"action": status}}
|
||||
r, _ = helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/bypass",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
if helpers.code_check(r) == 0:
|
||||
self.device_status = status
|
||||
return True
|
||||
logger.debug("%s offline", self.device_name)
|
||||
self.device_status = "off"
|
||||
self.connection_status = "offline"
|
||||
return False
|
||||
|
||||
def set_brightness(self, brightness: int) -> bool:
|
||||
"""Set brightness of tunable bulb."""
|
||||
if not self.dimmable_feature:
|
||||
logger.debug("%s is not dimmable", self.device_name)
|
||||
return False
|
||||
if brightness <= 0 or brightness > 100:
|
||||
logger.debug("Invalid brightness")
|
||||
return False
|
||||
|
||||
body = helpers.req_body(self.manager, "bypass")
|
||||
body["cid"] = self.cid
|
||||
body["configModule"] = self.config_module
|
||||
if self.device_status == "off":
|
||||
light_dict = {"action": "on", "brightness": brightness}
|
||||
else:
|
||||
light_dict = {"brightness": brightness}
|
||||
body["jsonCmd"] = {"light": light_dict}
|
||||
r, _ = helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/bypass",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self._brightness = brightness
|
||||
return True
|
||||
self.device_status = "off"
|
||||
self.connection_status = "offline"
|
||||
logger.debug("%s offline", self.device_name)
|
||||
|
||||
return False
|
||||
|
||||
def set_color_temp(self, color_temp: int) -> bool:
|
||||
"""Set Color Temperature of Bulb in pct (1 - 100)."""
|
||||
if color_temp < 0 or color_temp > 100:
|
||||
logger.debug("Invalid color temperature - only between 0 and 100")
|
||||
return False
|
||||
body = helpers.req_body(self.manager, "bypass")
|
||||
body["cid"] = self.cid
|
||||
body["jsonCmd"] = {"light": {}}
|
||||
if self.device_status == "off":
|
||||
light_dict = {"action": "on", "colorTempe": color_temp}
|
||||
else:
|
||||
light_dict = {"colorTempe": color_temp}
|
||||
body["jsonCmd"]["light"] = light_dict
|
||||
r, _ = helpers.call_api(
|
||||
"/cloud/v1/deviceManaged/bypass",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if not helpers.code_check(r):
|
||||
return False
|
||||
|
||||
if r.get("code") == -11300027:
|
||||
logger.debug("%s device offline", self.device_name)
|
||||
self.connection_status = "offline"
|
||||
self.device_status = "off"
|
||||
return False
|
||||
if r.get("code") == 0:
|
||||
self.device_status = "on"
|
||||
self._color_temp = color_temp
|
||||
return True
|
||||
logger.debug(
|
||||
"%s - Unknown return code - %d with message %s",
|
||||
self.device_name,
|
||||
r.get("code"),
|
||||
r.get("msg"),
|
||||
)
|
||||
return False
|
1325
custom_components/vesync/pyvesync/vesyncfan.py
Normal file
1325
custom_components/vesync/pyvesync/vesyncfan.py
Normal file
File diff suppressed because it is too large
Load Diff
703
custom_components/vesync/pyvesync/vesyncoutlet.py
Normal file
703
custom_components/vesync/pyvesync/vesyncoutlet.py
Normal file
@ -0,0 +1,703 @@
|
||||
"""Etekcity Outlets."""
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import json
|
||||
import logging
|
||||
import time
|
||||
|
||||
from .helpers import Helpers
|
||||
from .vesyncbasedevice import VeSyncBaseDevice
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
outlet_config = {
|
||||
"wifi-switch-1.3": {"module": "VeSyncOutlet7A"},
|
||||
"ESW03-USA": {"module": "VeSyncOutlet10A"},
|
||||
"ESW01-EU": {"module": "VeSyncOutlet10A"},
|
||||
"ESW15-USA": {"module": "VeSyncOutlet15A"},
|
||||
"ESO15-TB": {"module": "VeSyncOutdoorPlug"},
|
||||
}
|
||||
|
||||
outlet_modules = {k: v["module"] for k, v in outlet_config.items()}
|
||||
|
||||
__all__ = list(outlet_modules.values()) + ["outlet_modules"]
|
||||
|
||||
|
||||
class VeSyncOutlet(VeSyncBaseDevice):
|
||||
"""Base class for Etekcity Outlets."""
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize VeSync Outlet base class."""
|
||||
super().__init__(details, manager)
|
||||
|
||||
self.details = {}
|
||||
self.energy = {}
|
||||
self.update_energy_ts = None
|
||||
self._energy_update_interval = manager.energy_update_interval
|
||||
|
||||
@property
|
||||
def update_time_check(self) -> bool:
|
||||
"""Test if energy update interval has been exceeded."""
|
||||
if self.update_energy_ts is None:
|
||||
return True
|
||||
|
||||
if (time.time() - self.update_energy_ts) > self._energy_update_interval:
|
||||
return True
|
||||
return False
|
||||
|
||||
@abstractmethod
|
||||
def turn_on(self) -> bool:
|
||||
"""Return True if device has beeeen turned on."""
|
||||
|
||||
@abstractmethod
|
||||
def turn_off(self) -> bool:
|
||||
"""Return True if device has beeeen turned off."""
|
||||
|
||||
@abstractmethod
|
||||
def get_details(self) -> None:
|
||||
"""Build details dictionary."""
|
||||
|
||||
@abstractmethod
|
||||
def get_weekly_energy(self) -> None:
|
||||
"""Build weekly energy history dictionary."""
|
||||
|
||||
@abstractmethod
|
||||
def get_monthly_energy(self) -> None:
|
||||
"""Build Monthly Energy History Dictionary."""
|
||||
|
||||
@abstractmethod
|
||||
def get_yearly_energy(self):
|
||||
"""Build Yearly Energy Dictionary."""
|
||||
|
||||
@abstractmethod
|
||||
def get_config(self):
|
||||
"""Get configuration and firmware details."""
|
||||
|
||||
def update(self):
|
||||
"""Get Device Energy and Status."""
|
||||
self.get_details()
|
||||
|
||||
def update_energy(self, bypass_check: bool = False):
|
||||
"""Build weekly, monthly and yearly dictionaries."""
|
||||
if bypass_check or self.update_time_check:
|
||||
self.update_energy_ts = time.time()
|
||||
self.get_weekly_energy()
|
||||
if "week" in self.energy:
|
||||
self.get_monthly_energy()
|
||||
self.get_yearly_energy()
|
||||
if not bypass_check:
|
||||
self.update_energy_ts = time.time()
|
||||
|
||||
@property
|
||||
def active_time(self) -> int:
|
||||
"""Return active time of a device in minutes."""
|
||||
return self.details.get("active_time", 0)
|
||||
|
||||
@property
|
||||
def energy_today(self) -> float:
|
||||
"""Return energy."""
|
||||
return self.details.get("energy", 0)
|
||||
|
||||
@property
|
||||
def power(self) -> float:
|
||||
"""Return current power in watts."""
|
||||
return float(self.details.get("power", 0))
|
||||
|
||||
@property
|
||||
def voltage(self) -> float:
|
||||
"""Return current voltage."""
|
||||
return float(self.details.get("voltage", 0))
|
||||
|
||||
@property
|
||||
def monthly_energy_total(self) -> float:
|
||||
"""Return total energy usage over the month."""
|
||||
return self.energy.get("month", {}).get("total_energy", 0)
|
||||
|
||||
@property
|
||||
def weekly_energy_total(self) -> float:
|
||||
"""Return total energy usage over the week."""
|
||||
return self.energy.get("week", {}).get("total_energy", 0)
|
||||
|
||||
@property
|
||||
def yearly_energy_total(self) -> float:
|
||||
"""Return total energy usage over the year."""
|
||||
return self.energy.get("year", {}).get("total_energy", 0)
|
||||
|
||||
def display(self):
|
||||
"""Return formatted device info to stdout."""
|
||||
super().display()
|
||||
disp1 = [
|
||||
("Active Time : ", self.active_time, " minutes"),
|
||||
("Energy: ", self.energy_today, " kWh"),
|
||||
("Power: ", self.power, " Watts"),
|
||||
("Voltage: ", self.voltage, " Volts"),
|
||||
("Energy Week: ", self.weekly_energy_total, " kWh"),
|
||||
("Energy Month: ", self.monthly_energy_total, " kWh"),
|
||||
("Energy Year: ", self.yearly_energy_total, " kWh"),
|
||||
]
|
||||
for line in disp1:
|
||||
print(f"{line[0]:.<15} {line[1]} {line[2]}")
|
||||
|
||||
def displayJSON(self):
|
||||
"""Return JSON details for outlet."""
|
||||
sup = super().displayJSON()
|
||||
sup_val = json.loads(sup)
|
||||
sup_val.update(
|
||||
{
|
||||
"Active Time": str(self.active_time),
|
||||
"Energy": str(self.energy_today),
|
||||
"Power": str(self.power),
|
||||
"Voltage": str(self.voltage),
|
||||
"Energy Week": str(self.weekly_energy_total),
|
||||
"Energy Month": str(self.monthly_energy_total),
|
||||
"Energy Year": str(self.yearly_energy_total),
|
||||
}
|
||||
)
|
||||
|
||||
return sup_val
|
||||
|
||||
|
||||
class VeSyncOutlet7A(VeSyncOutlet):
|
||||
"""Etekcity 7A Round Outlet Class."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize Etekcity 7A round outlet class."""
|
||||
super().__init__(details, manager)
|
||||
self.det_keys = ["deviceStatus", "activeTime", "energy", "power", "voltage"]
|
||||
self.energy_keys = ["energyConsumptionOfToday", "maxEnergy", "totalEnergy"]
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get 7A outlet details."""
|
||||
r, _ = Helpers.call_api(
|
||||
f"/v1/device/{self.cid}/detail",
|
||||
"get",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if r is not None and all(x in r for x in self.det_keys):
|
||||
self.device_status = r.get("deviceStatus", self.device_status)
|
||||
self.details["active_time"] = r.get("activeTime", 0)
|
||||
self.details["energy"] = r.get("energy", 0)
|
||||
power = r.get("power", "0:0")
|
||||
power = round(float(Helpers.calculate_hex(power)), 2)
|
||||
self.details["power"] = power
|
||||
voltage = r.get("voltage", "0:0")
|
||||
voltage = round(float(Helpers.calculate_hex(voltage)), 2)
|
||||
self.details["voltage"] = voltage
|
||||
else:
|
||||
logger.debug("Unable to get %s details", self.device_name)
|
||||
|
||||
def get_weekly_energy(self) -> None:
|
||||
"""Get 7A outlet weekly energy info and build weekly energy dict."""
|
||||
r, _ = Helpers.call_api(
|
||||
f"/v1/device/{self.cid}/energy/week",
|
||||
"get",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if r is not None and all(x in r for x in self.energy_keys):
|
||||
self.energy["week"] = Helpers.build_energy_dict(r)
|
||||
else:
|
||||
logger.debug("Unable to get %s weekly data", self.device_name)
|
||||
|
||||
def get_monthly_energy(self) -> None:
|
||||
"""Get 7A outlet monthly energy info and build monthly energy dict."""
|
||||
r, _ = Helpers.call_api(
|
||||
f"/v1/device/{self.cid}/energy/month",
|
||||
"get",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if r is not None and all(x in r for x in self.energy_keys):
|
||||
self.energy["month"] = Helpers.build_energy_dict(r)
|
||||
else:
|
||||
logger.warning("Unable to get %s monthly data", self.device_name)
|
||||
|
||||
def get_yearly_energy(self) -> None:
|
||||
"""Get 7A outlet yearly energy info and build yearly energy dict."""
|
||||
r, _ = Helpers.call_api(
|
||||
f"/v1/device/{self.cid}/energy/year",
|
||||
"get",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if r is not None and all(x in r for x in self.energy_keys):
|
||||
self.energy["year"] = Helpers.build_energy_dict(r)
|
||||
else:
|
||||
logger.debug("Unable to get %s yearly data", self.device_name)
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn 7A outlet on - return True if successful."""
|
||||
return self._toggle("on")
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn 7A outlet off - return True if successful."""
|
||||
return self._toggle("off")
|
||||
|
||||
def _toggle(self, state):
|
||||
_, status_code = Helpers.call_api(
|
||||
f"/v1/wifi-switch-1.3/{self.cid}/status/{state}",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if status_code is not None and status_code == 200:
|
||||
self.device_status = state
|
||||
return True
|
||||
logger.warning("Error turning %s %s", self.device_name, state)
|
||||
return False
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get 7A outlet configuration info."""
|
||||
r, _ = Helpers.call_api(
|
||||
f"/v1/device/{self.cid}/configurations",
|
||||
"get",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
)
|
||||
|
||||
if "currentFirmVersion" in r:
|
||||
self.config = Helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.debug("Error getting configuration info for %s", self.device_name)
|
||||
|
||||
|
||||
class VeSyncOutlet10A(VeSyncOutlet):
|
||||
"""Etekcity 10A Round Outlets."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize 10A outlet class."""
|
||||
super().__init__(details, manager)
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get 10A outlet details."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = Helpers.call_api(
|
||||
"/10a/v1/device/devicedetail",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(r):
|
||||
self.device_status = r.get("deviceStatus", self.device_status)
|
||||
self.connection_status = r.get("connectionStatus", self.connection_status)
|
||||
self.details = Helpers.build_details_dict(r)
|
||||
else:
|
||||
logger.debug("Unable to get %s details", self.device_name)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get 10A outlet configuration info."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = Helpers.call_api(
|
||||
"/10a/v1/device/configurations",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(r):
|
||||
self.config = Helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.debug("Error getting %s config info", self.device_name)
|
||||
|
||||
def get_weekly_energy(self) -> None:
|
||||
"""Get 10A outlet weekly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_week")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/10a/v1/device/energyweek",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["week"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s weekly data", self.device_name)
|
||||
|
||||
def get_monthly_energy(self) -> None:
|
||||
"""Get 10A outlet monthly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_month")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/10a/v1/device/energymonth",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["month"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s monthly data", self.device_name)
|
||||
|
||||
def get_yearly_energy(self) -> None:
|
||||
"""Get 10A outlet yearly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_year")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/10a/v1/device/energyyear",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["year"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s yearly data", self.device_name)
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn 10A outlet on - return True if successful."""
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = "on"
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/10a/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.device_status = "on"
|
||||
return True
|
||||
logger.warning("Error turning %s on", self.device_name)
|
||||
return False
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn 10A outlet off - return True if successful."""
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = "off"
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/10a/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.device_status = "off"
|
||||
return True
|
||||
logger.warning("Error turning %s off", self.device_name)
|
||||
return False
|
||||
|
||||
|
||||
class VeSyncOutlet15A(VeSyncOutlet):
|
||||
"""Class for Etekcity 15A Rectangular Outlets."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize 15A rectangular outlets."""
|
||||
super().__init__(details, manager)
|
||||
self.nightlight_status = "off"
|
||||
self.nightlight_brightness = 0
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get 15A outlet details."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = Helpers.call_api(
|
||||
"/15a/v1/device/devicedetail",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
attr_list = (
|
||||
"deviceStatus",
|
||||
"activeTime",
|
||||
"energy",
|
||||
"power",
|
||||
"voltage",
|
||||
"nightLightStatus",
|
||||
"nightLightAutomode",
|
||||
"nightLightBrightness",
|
||||
)
|
||||
|
||||
if Helpers.code_check(r) and all(k in r for k in attr_list):
|
||||
|
||||
self.device_status = r.get("deviceStatus")
|
||||
self.connection_status = r.get("connectionStatus")
|
||||
self.nightlight_status = r.get("nightLightStatus")
|
||||
self.nightlight_brightness = r.get("nightLightBrightness")
|
||||
self.details = Helpers.build_details_dict(r)
|
||||
else:
|
||||
logger.debug("Unable to get %s details", self.device_name)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get 15A outlet configuration info."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = Helpers.call_api(
|
||||
"/15a/v1/device/configurations",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(r):
|
||||
self.config = Helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.debug("Unable to get %s config info", self.device_name)
|
||||
|
||||
def get_weekly_energy(self) -> None:
|
||||
"""Get 15A outlet weekly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_week")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/energyweek",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["week"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s weekly data", self.device_name)
|
||||
|
||||
def get_monthly_energy(self) -> None:
|
||||
"""Get 15A outlet monthly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_month")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/energymonth",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["month"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s monthly data", self.device_name)
|
||||
|
||||
def get_yearly_energy(self) -> None:
|
||||
"""Get 15A outlet yearly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_year")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/energyyear",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["year"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s yearly data", self.device_name)
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn 15A outlet on - return True if successful."""
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = "on"
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.device_status = "on"
|
||||
return True
|
||||
logger.warning("Error turning %s on", self.device_name)
|
||||
return False
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn 15A outlet off - return True if successful."""
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = "off"
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.device_status = "off"
|
||||
return True
|
||||
|
||||
logger.warning("Error turning %s off", self.device_name)
|
||||
return False
|
||||
|
||||
def turn_on_nightlight(self) -> bool:
|
||||
"""Turn on nightlight."""
|
||||
return self._extracted_from_turn_off_nightlight_3("auto")
|
||||
|
||||
def turn_off_nightlight(self) -> bool:
|
||||
"""Turn Off Nightlight."""
|
||||
return self._extracted_from_turn_off_nightlight_3("manual")
|
||||
|
||||
def _extracted_from_turn_off_nightlight_3(self, mode):
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["mode"] = mode
|
||||
response, _ = Helpers.call_api(
|
||||
"/15a/v1/device/nightlightstatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
return True
|
||||
logger.debug(
|
||||
"Error turning %s %s nightlight",
|
||||
"on" if mode == "auto" else "off",
|
||||
self.device_name,
|
||||
)
|
||||
return False
|
||||
|
||||
|
||||
class VeSyncOutdoorPlug(VeSyncOutlet):
|
||||
"""Class to hold Etekcity outdoor outlets."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize Etekcity Outdoor Plug class."""
|
||||
super().__init__(details, manager)
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get details for outdoor outlet."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
r, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/devicedetail",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(r):
|
||||
self.details = Helpers.build_details_dict(r)
|
||||
self.connection_status = r.get("connectionStatus")
|
||||
|
||||
dev_no = self.sub_device_no
|
||||
sub_device_list = r.get("subDevices")
|
||||
if sub_device_list and dev_no <= len(sub_device_list):
|
||||
self.device_status = sub_device_list[(dev_no + -1)].get(
|
||||
"subDeviceStatus"
|
||||
)
|
||||
return
|
||||
logger.debug("Unable to get %s details", self.device_name)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get configuration info for outdoor outlet."""
|
||||
body = Helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/configurations",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(r):
|
||||
self.config = Helpers.build_config_dict(r)
|
||||
logger.debug("Error getting %s config info", self.device_name)
|
||||
|
||||
def get_weekly_energy(self) -> None:
|
||||
"""Get outdoor outlet weekly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_week")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/energyweek",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["week"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s weekly data", self.device_name)
|
||||
|
||||
def get_monthly_energy(self) -> None:
|
||||
"""Get outdoor outlet monthly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_month")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/energymonth",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["month"] = Helpers.build_energy_dict(response)
|
||||
logger.debug("Unable to get %s monthly data", self.device_name)
|
||||
|
||||
def get_yearly_energy(self) -> None:
|
||||
"""Get outdoor outlet yearly energy info and populate energy dict."""
|
||||
body = Helpers.req_body(self.manager, "energy_year")
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/energyyear",
|
||||
"post",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.energy["year"] = Helpers.build_energy_dict(response)
|
||||
else:
|
||||
logger.debug("Unable to get %s yearly data", self.device_name)
|
||||
|
||||
def toggle(self, status) -> bool:
|
||||
"""Toggle power for outdoor outlet."""
|
||||
body = Helpers.req_body(self.manager, "devicestatus")
|
||||
body["uuid"] = self.uuid
|
||||
body["status"] = status
|
||||
body["switchNo"] = self.sub_device_no
|
||||
|
||||
response, _ = Helpers.call_api(
|
||||
"/outdoorsocket15a/v1/device/devicestatus",
|
||||
"put",
|
||||
headers=Helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if Helpers.code_check(response):
|
||||
self.device_status = status
|
||||
return True
|
||||
logger.warning("Error turning %s %s", self.device_name, status)
|
||||
return False
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn outdoor outlet on and return True if successful."""
|
||||
return bool(self.toggle("on"))
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn outdoor outlet off and return True if successful."""
|
||||
return bool(self.toggle("off"))
|
347
custom_components/vesync/pyvesync/vesyncswitch.py
Normal file
347
custom_components/vesync/pyvesync/vesyncswitch.py
Normal file
@ -0,0 +1,347 @@
|
||||
"""Classes for VeSync Switch Devices."""
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, Union
|
||||
|
||||
from .helpers import Helpers as helpers
|
||||
from .vesyncbasedevice import VeSyncBaseDevice
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
feature_dict: Dict[str, Dict[str, Union[list, str]]] = {
|
||||
"ESWL01": {"module": "VeSyncWallSwitch", "features": []},
|
||||
"ESWD16": {"module": "VeSyncDimmerSwitch", "features": ["dimmable"]},
|
||||
"ESWL03": {"module": "VeSyncWallSwitch", "features": []},
|
||||
}
|
||||
|
||||
switch_modules: dict = {k: v["module"] for k, v in feature_dict.items()}
|
||||
|
||||
__all__: list = list(switch_modules.values()) + ["switch_modules"]
|
||||
|
||||
|
||||
class VeSyncSwitch(VeSyncBaseDevice):
|
||||
"""Etekcity Switch Base Class."""
|
||||
|
||||
__metaclasss__ = ABCMeta
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize Switch Base Class."""
|
||||
super().__init__(details, manager)
|
||||
self.features = feature_dict.get(self.device_type, {}).get("features")
|
||||
if self.features is None:
|
||||
logger.error("No configuration set for - %s", self.device_name)
|
||||
raise RuntimeError(f"No configuration set for - {self.device_name}")
|
||||
self.details = {}
|
||||
|
||||
def is_dimmable(self) -> bool:
|
||||
"""Return True if switch is dimmable."""
|
||||
return bool("dimmable" in self.features)
|
||||
|
||||
@abstractmethod
|
||||
def get_details(self) -> None:
|
||||
"""Get Device Details."""
|
||||
|
||||
@abstractmethod
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn Switch On."""
|
||||
|
||||
@abstractmethod
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn switch off."""
|
||||
|
||||
@abstractmethod
|
||||
def get_config(self) -> None:
|
||||
"""Get configuration and firmware deatils."""
|
||||
|
||||
@property
|
||||
def active_time(self) -> int:
|
||||
"""Get active time of switch."""
|
||||
return self.details.get("active_time", 0)
|
||||
|
||||
def update(self) -> None:
|
||||
"""Update device details."""
|
||||
self.get_details()
|
||||
|
||||
|
||||
class VeSyncWallSwitch(VeSyncSwitch):
|
||||
"""Etekcity standard wall switch class."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize standard etekcity wall switch class."""
|
||||
super().__init__(details, manager)
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get switch device details."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/inwallswitch/v1/device/devicedetail", "post", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = r.get("deviceStatus", self.device_status)
|
||||
self.details["active_time"] = r.get("activeTime", 0)
|
||||
self.connection_status = r.get("connectionStatus", self.connection_status)
|
||||
else:
|
||||
logger.debug("Error getting %s details", self.device_name)
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get switch device configuration info."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/inwallswitch/v1/device/configurations",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self.config = helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.warning("Unable to get %s config info", self.device_name)
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn off switch device."""
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["status"] = "off"
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/inwallswitch/v1/device/devicestatus", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = "off"
|
||||
return True
|
||||
logger.warning("Error turning %s off", self.device_name)
|
||||
return False
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn on switch device."""
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["status"] = "on"
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/inwallswitch/v1/device/devicestatus", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = "on"
|
||||
return True
|
||||
logger.warning("Error turning %s on", self.device_name)
|
||||
return False
|
||||
|
||||
|
||||
class VeSyncDimmerSwitch(VeSyncSwitch):
|
||||
"""Vesync Dimmer Switch Class with RGB Faceplate."""
|
||||
|
||||
def __init__(self, details, manager):
|
||||
"""Initialize dimmer switch class."""
|
||||
super().__init__(details, manager)
|
||||
self._brightness = 0
|
||||
self._rgb_value = {"red": 0, "blue": 0, "green": 0}
|
||||
self._rgb_status = "unknown"
|
||||
self._indicator_light = "unknown"
|
||||
|
||||
def get_details(self) -> None:
|
||||
"""Get dimmer switch details."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/devicedetail", "post", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = r.get("deviceStatus", self.device_status)
|
||||
self.details["active_time"] = r.get("activeTime", 0)
|
||||
self.connection_status = r.get("connectionStatus", self.connection_status)
|
||||
self._brightness = r.get("brightness")
|
||||
self._rgb_status = r.get("rgbStatus")
|
||||
self._rgb_value = r.get("rgbValue")
|
||||
self._indicator_light = r.get("indicatorlightStatus")
|
||||
else:
|
||||
logger.debug("Error getting %s details", self.device_name)
|
||||
|
||||
@property
|
||||
def brightness(self) -> float:
|
||||
"""Return brightness in percent."""
|
||||
return self._brightness
|
||||
|
||||
@property
|
||||
def indicator_light_status(self) -> str:
|
||||
"""Faceplate brightness light status."""
|
||||
return self._indicator_light
|
||||
|
||||
@property
|
||||
def rgb_light_status(self) -> str:
|
||||
"""RGB Faceplate light status."""
|
||||
return self._rgb_status
|
||||
|
||||
@property
|
||||
def rgb_light_value(self) -> dict:
|
||||
"""RGB Light Values."""
|
||||
return self._rgb_value
|
||||
|
||||
def switch_toggle(self, status: str) -> bool:
|
||||
"""Toggle switch status."""
|
||||
if status not in ["on", "off"]:
|
||||
logger.debug("Invalid status passed to wall switch")
|
||||
return False
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["status"] = status
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/devicestatus", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = status
|
||||
return True
|
||||
|
||||
logger.warning("Error turning %s %s", self.device_name, status)
|
||||
return False
|
||||
|
||||
def turn_on(self) -> bool:
|
||||
"""Turn switch on."""
|
||||
return self.switch_toggle("on")
|
||||
|
||||
def turn_off(self) -> bool:
|
||||
"""Turn switch off."""
|
||||
return self.switch_toggle("off")
|
||||
|
||||
def indicator_light_toggle(self, status: str) -> bool:
|
||||
"""Toggle indicator light."""
|
||||
if status not in ["on", "off"]:
|
||||
logger.debug("Invalid status for wall switch")
|
||||
return False
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["status"] = status
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/indicatorlightstatus", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self.device_status = status
|
||||
return True
|
||||
|
||||
logger.warning("Error turning %s indicator light %s", self.device_name, status)
|
||||
return False
|
||||
|
||||
def indicator_light_on(self) -> bool:
|
||||
"""Turn Indicator light on."""
|
||||
return self.indicator_light_toggle("on")
|
||||
|
||||
def indicator_light_off(self) -> bool:
|
||||
"""Turn indicator light off."""
|
||||
return self.indicator_light_toggle("off")
|
||||
|
||||
def rgb_color_status(
|
||||
self, status: str, red: int = None, blue: int = None, green: int = None
|
||||
) -> bool:
|
||||
"""Set faceplate RGB color."""
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["status"] = status
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
if red is not None and blue is not None and green is not None:
|
||||
body["rgbValue"] = {"red": red, "blue": blue, "green": green}
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/devicergbstatus", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self._rgb_status = status
|
||||
if body.get("rgbValue") is not None:
|
||||
self._rgb_value = {"red": red, "blue": blue, "green": green}
|
||||
return True
|
||||
logger.warning("Error turning %s off", self.device_name)
|
||||
return False
|
||||
|
||||
def rgb_color_off(self) -> bool:
|
||||
"""Turn RGB Color Off."""
|
||||
return self.rgb_color_status("off")
|
||||
|
||||
def rgb_color_on(self) -> bool:
|
||||
"""Turn RGB Color Off."""
|
||||
return self.rgb_color_status("on")
|
||||
|
||||
def rgb_color_set(self, red: int, green: int, blue: int) -> bool:
|
||||
"""Set RGB color of faceplate."""
|
||||
if isinstance(red, int) and isinstance(green, int) and isinstance(blue, int):
|
||||
for color in [red, green, blue]:
|
||||
if color < 0 or color > 255:
|
||||
logger.warning("Invalid RGB value")
|
||||
return False
|
||||
|
||||
return bool(self.rgb_color_status("on", red, green, blue))
|
||||
return False
|
||||
|
||||
def set_brightness(self, brightness: int) -> bool:
|
||||
"""Set brightness of dimmer - 1 - 100."""
|
||||
if isinstance(brightness, int) and (brightness > 0 or brightness <= 100):
|
||||
|
||||
body = helpers.req_body(self.manager, "devicestatus")
|
||||
body["brightness"] = brightness
|
||||
body["uuid"] = self.uuid
|
||||
head = helpers.req_headers(self.manager)
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/updatebrightness", "put", headers=head, json=body
|
||||
)
|
||||
|
||||
if r is not None and helpers.code_check(r):
|
||||
self._brightness = brightness
|
||||
return True
|
||||
logger.warning("Error setting %s brightness", self.device_name)
|
||||
else:
|
||||
logger.warning("Invalid brightness")
|
||||
return False
|
||||
|
||||
def displayJSON(self) -> str:
|
||||
"""JSON API for dimmer switch."""
|
||||
sup_val = json.loads(super().displayJSON())
|
||||
if self.is_dimmable:
|
||||
sup_val.update(
|
||||
{
|
||||
"Indicator Light": str(self.active_time),
|
||||
"Brightness": str(self._brightness),
|
||||
"RGB Light": str(self._rgb_status),
|
||||
}
|
||||
)
|
||||
return sup_val
|
||||
|
||||
def get_config(self) -> None:
|
||||
"""Get dimmable switch device configuration info."""
|
||||
body = helpers.req_body(self.manager, "devicedetail")
|
||||
body["method"] = "configurations"
|
||||
body["uuid"] = self.uuid
|
||||
|
||||
r, _ = helpers.call_api(
|
||||
"/dimmer/v1/device/configurations",
|
||||
"post",
|
||||
headers=helpers.req_headers(self.manager),
|
||||
json=body,
|
||||
)
|
||||
|
||||
if helpers.code_check(r):
|
||||
self.config = helpers.build_config_dict(r)
|
||||
else:
|
||||
logger.warning("Unable to get %s config info", self.device_name)
|
202
custom_components/vesync/sensor.py
Normal file
202
custom_components/vesync/sensor.py
Normal file
@ -0,0 +1,202 @@
|
||||
"""Support for power & energy sensors for VeSync outlets."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ENERGY_KILO_WATT_HOUR, PERCENTAGE, POWER_WATT
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncBaseEntity, is_humidifier
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_SENSORS
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up switches."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SENSORS), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_SENSORS], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet":
|
||||
entities.extend((VeSyncPowerSensor(dev), VeSyncEnergySensor(dev)))
|
||||
elif is_humidifier(dev.device_type):
|
||||
entities.append(VeSyncHumiditySensor(dev))
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncOutletSensorEntity(VeSyncBaseEntity, SensorEntity):
|
||||
"""Representation of a sensor describing diagnostics of a VeSync outlet."""
|
||||
|
||||
def __init__(self, plug):
|
||||
"""Initialize the VeSync outlet device."""
|
||||
super().__init__(plug)
|
||||
self.smartplug = plug
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the diagnostic entity category."""
|
||||
return EntityCategory.DIAGNOSTIC
|
||||
|
||||
|
||||
class VeSyncPowerSensor(VeSyncOutletSensorEntity):
|
||||
"""Representation of current power use for a VeSync outlet."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return unique ID for power sensor on device."""
|
||||
return f"{super().unique_id}-power"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return sensor name."""
|
||||
return f"{super().name} current power"
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the power device class."""
|
||||
return SensorDeviceClass.POWER
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the current power usage in W."""
|
||||
return self.smartplug.power
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return the Watt unit of measurement."""
|
||||
return POWER_WATT
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
"""Return the measurement state class."""
|
||||
return SensorStateClass.MEASUREMENT
|
||||
|
||||
def update(self):
|
||||
"""Update outlet details and energy usage."""
|
||||
self.smartplug.update()
|
||||
self.smartplug.update_energy()
|
||||
|
||||
|
||||
class VeSyncEnergySensor(VeSyncOutletSensorEntity):
|
||||
"""Representation of current day's energy use for a VeSync outlet."""
|
||||
|
||||
def __init__(self, plug):
|
||||
"""Initialize the VeSync outlet device."""
|
||||
super().__init__(plug)
|
||||
self.smartplug = plug
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return unique ID for power sensor on device."""
|
||||
return f"{super().unique_id}-energy"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return sensor name."""
|
||||
return f"{super().name} energy use today"
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the energy device class."""
|
||||
return SensorDeviceClass.ENERGY
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the today total energy usage in kWh."""
|
||||
return self.smartplug.energy_today
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return the kWh unit of measurement."""
|
||||
return ENERGY_KILO_WATT_HOUR
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
"""Return the total_increasing state class."""
|
||||
return SensorStateClass.TOTAL_INCREASING
|
||||
|
||||
def update(self):
|
||||
"""Update outlet details and energy usage."""
|
||||
self.smartplug.update()
|
||||
self.smartplug.update_energy()
|
||||
|
||||
|
||||
class VeSyncHumidifierSensorEntity(VeSyncBaseEntity, SensorEntity):
|
||||
"""Representation of a sensor describing diagnostics of a VeSync humidifier."""
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the diagnostic entity category."""
|
||||
return EntityCategory.DIAGNOSTIC
|
||||
|
||||
|
||||
class VeSyncHumiditySensor(VeSyncHumidifierSensorEntity):
|
||||
"""Representation of current humidity for a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return unique ID for humidity sensor on device."""
|
||||
return f"{super().unique_id}-humidity"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return sensor name."""
|
||||
return f"{super().name} current humidity"
|
||||
|
||||
@property
|
||||
def device_class(self):
|
||||
"""Return the humidity device class."""
|
||||
return SensorDeviceClass.HUMIDITY
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the current humidity in percent."""
|
||||
return self.smarthumidifier.details["humidity"]
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return the % unit of measurement."""
|
||||
return PERCENTAGE
|
||||
|
||||
@property
|
||||
def state_class(self):
|
||||
"""Return the measurement state class."""
|
||||
return SensorStateClass.MEASUREMENT
|
3
custom_components/vesync/services.yaml
Normal file
3
custom_components/vesync/services.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
update_devices:
|
||||
name: Update devices
|
||||
description: Add new VeSync devices to Home Assistant
|
19
custom_components/vesync/strings.json
Normal file
19
custom_components/vesync/strings.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Enter Username and Password",
|
||||
"data": {
|
||||
"username": "[%key:common::config_flow::data::email%]",
|
||||
"password": "[%key:common::config_flow::data::password%]"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]"
|
||||
},
|
||||
"abort": {
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
}
|
||||
}
|
||||
}
|
203
custom_components/vesync/switch.py
Normal file
203
custom_components/vesync/switch.py
Normal file
@ -0,0 +1,203 @@
|
||||
"""Support for VeSync switches."""
|
||||
import logging
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .common import VeSyncBaseEntity, VeSyncDevice, is_humidifier
|
||||
from .const import DEV_TYPE_TO_HA, DOMAIN, VS_DISCOVERY, VS_SWITCHES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up switches."""
|
||||
|
||||
@callback
|
||||
def discover(devices):
|
||||
"""Add new devices to platform."""
|
||||
_setup_entities(devices, async_add_entities)
|
||||
|
||||
config_entry.async_on_unload(
|
||||
async_dispatcher_connect(hass, VS_DISCOVERY.format(VS_SWITCHES), discover)
|
||||
)
|
||||
|
||||
_setup_entities(
|
||||
hass.data[DOMAIN][config_entry.entry_id][VS_SWITCHES], async_add_entities
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _setup_entities(devices, async_add_entities):
|
||||
"""Check if device is online and add entity."""
|
||||
entities = []
|
||||
for dev in devices:
|
||||
if DEV_TYPE_TO_HA.get(dev.device_type) == "outlet":
|
||||
entities.append(VeSyncSwitchHA(dev))
|
||||
elif DEV_TYPE_TO_HA.get(dev.device_type) == "switch":
|
||||
entities.append(VeSyncLightSwitch(dev))
|
||||
elif is_humidifier(dev.device_type):
|
||||
entities.extend(
|
||||
(
|
||||
VeSyncHumidifierDisplayHA(dev),
|
||||
VeSyncHumidifierAutomaticStopHA(dev),
|
||||
VeSyncHumidifierAutoOnHA(dev),
|
||||
)
|
||||
)
|
||||
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
"%s - Unknown device type - %s", dev.device_name, dev.device_type
|
||||
)
|
||||
continue
|
||||
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
class VeSyncBaseSwitch(VeSyncDevice, SwitchEntity):
|
||||
"""Base class for VeSync switch Device Representations."""
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the device on."""
|
||||
self.device.turn_on()
|
||||
|
||||
|
||||
class VeSyncSwitchHA(VeSyncBaseSwitch, SwitchEntity):
|
||||
"""Representation of a VeSync switch."""
|
||||
|
||||
def __init__(self, plug):
|
||||
"""Initialize the VeSync switch device."""
|
||||
super().__init__(plug)
|
||||
self.smartplug = plug
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes of the device."""
|
||||
return (
|
||||
{
|
||||
"voltage": self.smartplug.voltage,
|
||||
"weekly_energy_total": self.smartplug.weekly_energy_total,
|
||||
"monthly_energy_total": self.smartplug.monthly_energy_total,
|
||||
"yearly_energy_total": self.smartplug.yearly_energy_total,
|
||||
}
|
||||
if hasattr(self.smartplug, "weekly_energy_total")
|
||||
else {}
|
||||
)
|
||||
|
||||
def update(self):
|
||||
"""Update outlet details and energy usage."""
|
||||
self.smartplug.update()
|
||||
self.smartplug.update_energy()
|
||||
|
||||
|
||||
class VeSyncLightSwitch(VeSyncBaseSwitch, SwitchEntity):
|
||||
"""Handle representation of VeSync Light Switch."""
|
||||
|
||||
def __init__(self, switch):
|
||||
"""Initialize Light Switch device class."""
|
||||
super().__init__(switch)
|
||||
self.switch = switch
|
||||
|
||||
|
||||
class VeSyncHumidifierSwitchEntity(VeSyncBaseEntity, SwitchEntity):
|
||||
"""Representation of a switch for configuring a VeSync humidifier."""
|
||||
|
||||
def __init__(self, humidifier):
|
||||
"""Initialize the VeSync humidifier device."""
|
||||
super().__init__(humidifier)
|
||||
self.smarthumidifier = humidifier
|
||||
|
||||
@property
|
||||
def entity_category(self):
|
||||
"""Return the configuration entity category."""
|
||||
return EntityCategory.CONFIG
|
||||
|
||||
|
||||
class VeSyncHumidifierDisplayHA(VeSyncHumidifierSwitchEntity):
|
||||
"""Representation of the display on a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this display."""
|
||||
return f"{super().unique_id}-display"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the display."""
|
||||
return f"{super().name} display"
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if display is on."""
|
||||
return self.device.details["display"]
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the display on."""
|
||||
self.device.turn_on_display()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the display off."""
|
||||
self.device.turn_off_display()
|
||||
|
||||
|
||||
class VeSyncHumidifierAutomaticStopHA(VeSyncHumidifierSwitchEntity):
|
||||
"""Representation of the automatic stop toggle on a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
return f"{super().unique_id}-automatic-stop"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return f"{super().name} automatic stop"
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if automatic stop is on."""
|
||||
return self.device.config["automatic_stop"]
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the automatic stop on."""
|
||||
self.device.automatic_stop_on()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the automatic stop off."""
|
||||
self.device.automatic_stop_off()
|
||||
|
||||
|
||||
class VeSyncHumidifierAutoOnHA(VeSyncHumidifierSwitchEntity):
|
||||
"""Provide switch to turn off auto mode and set manual mist level 1 on a VeSync humidifier."""
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return the ID of this device."""
|
||||
return f"{super().unique_id}-auto-mode"
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the device."""
|
||||
return f"{super().name} auto mode"
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return True if in auto mode."""
|
||||
return self.device.details["mode"] == "auto"
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn auto mode on."""
|
||||
self.device.set_auto_mode()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn auto off by setting manual and mist level 1."""
|
||||
self.device.set_manual_mode()
|
||||
self.device.set_mist_level(1)
|
13
custom_components/vesync/translations/bg.json
Normal file
13
custom_components/vesync/translations/bg.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u0430",
|
||||
"username": "E-mail \u0430\u0434\u0440\u0435\u0441"
|
||||
},
|
||||
"title": "\u0412\u044a\u0432\u0435\u0434\u0435\u0442\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435 \u0438 \u043f\u0430\u0440\u043e\u043b\u0430"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/ca.json
Normal file
19
custom_components/vesync/translations/ca.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ja configurat. Nom\u00e9s \u00e9s possible una sola configuraci\u00f3."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Autenticaci\u00f3 inv\u00e0lida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Contrasenya",
|
||||
"username": "Correu electr\u00f2nic"
|
||||
},
|
||||
"title": "Introdueix el nom d'usuari i contrasenya"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/cs.json
Normal file
19
custom_components/vesync/translations/cs.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ji\u017e nastaveno. Je mo\u017en\u00e1 pouze jedin\u00e1 konfigurace."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Neplatn\u00e9 ov\u011b\u0159en\u00ed"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Heslo",
|
||||
"username": "E-mail"
|
||||
},
|
||||
"title": "Zadejte u\u017eivatelsk\u00e9 jm\u00e9no a heslo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
custom_components/vesync/translations/da.json
Normal file
13
custom_components/vesync/translations/da.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Adgangskode",
|
||||
"username": "Emailadresse"
|
||||
},
|
||||
"title": "Indtast brugernavn og adgangskode"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/de.json
Normal file
19
custom_components/vesync/translations/de.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Bereits konfiguriert. Nur eine einzige Konfiguration m\u00f6glich."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Ung\u00fcltige Authentifizierung"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Passwort",
|
||||
"username": "E-Mail"
|
||||
},
|
||||
"title": "Benutzername und Passwort eingeben"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/el.json
Normal file
19
custom_components/vesync/translations/el.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u0388\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03c1\u03c5\u03b8\u03bc\u03b9\u03c3\u03c4\u03b5\u03af. \u039c\u03cc\u03bd\u03bf \u03bc\u03af\u03b1 \u03b4\u03b9\u03b1\u03bc\u03cc\u03c1\u03c6\u03c9\u03c3\u03b7 \u03b5\u03af\u03bd\u03b1\u03b9 \u03b4\u03c5\u03bd\u03b1\u03c4\u03ae."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\u039c\u03b7 \u03ad\u03b3\u03ba\u03c5\u03c1\u03bf\u03c2 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u039a\u03c9\u03b4\u03b9\u03ba\u03cc\u03c2 \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2",
|
||||
"username": "Email"
|
||||
},
|
||||
"title": "\u0395\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03cc\u03bd\u03bf\u03bc\u03b1 \u03c7\u03c1\u03ae\u03c3\u03c4\u03b7 \u03ba\u03b1\u03b9 \u03ba\u03c9\u03b4\u03b9\u03ba\u03cc \u03c0\u03c1\u03cc\u03c3\u03b2\u03b1\u03c3\u03b7\u03c2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/en.json
Normal file
19
custom_components/vesync/translations/en.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Already configured. Only a single configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Invalid authentication"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Password",
|
||||
"username": "Email"
|
||||
},
|
||||
"title": "Enter Username and Password"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
custom_components/vesync/translations/es-419.json
Normal file
13
custom_components/vesync/translations/es-419.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Contrase\u00f1a",
|
||||
"username": "Direcci\u00f3n de correo electr\u00f3nico"
|
||||
},
|
||||
"title": "Ingrese nombre de usuario y contrase\u00f1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/es.json
Normal file
19
custom_components/vesync/translations/es.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ya est\u00e1 configurado. Solo es posible una \u00fanica configuraci\u00f3n."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Autenticaci\u00f3n no v\u00e1lida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Contrase\u00f1a",
|
||||
"username": "Correo electr\u00f3nico"
|
||||
},
|
||||
"title": "Introduzca el nombre de usuario y la contrase\u00f1a"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/et.json
Normal file
19
custom_components/vesync/translations/et.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Juba seadistatud. V\u00f5imalik on ainult \u00fcks seadistamine."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Tuvastamise viga"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Salas\u00f5na",
|
||||
"username": "E-post"
|
||||
},
|
||||
"title": "Sisesta kasutajanimi ja salas\u00f5na"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/fr.json
Normal file
19
custom_components/vesync/translations/fr.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "D\u00e9j\u00e0 configur\u00e9. Une seule configuration possible."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Authentification invalide"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Mot de passe",
|
||||
"username": "Email"
|
||||
},
|
||||
"title": "Entrez vos identifiants"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/he.json
Normal file
19
custom_components/vesync/translations/he.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u05ea\u05e6\u05d5\u05e8\u05ea\u05d5 \u05db\u05d1\u05e8 \u05e0\u05e7\u05d1\u05e2\u05d4. \u05e8\u05e7 \u05ea\u05e6\u05d5\u05e8\u05d4 \u05d0\u05d7\u05ea \u05d0\u05e4\u05e9\u05e8\u05d9\u05ea."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\u05d0\u05d9\u05de\u05d5\u05ea \u05dc\u05d0 \u05d7\u05d5\u05e7\u05d9"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u05e1\u05d9\u05e1\u05de\u05d4",
|
||||
"username": "\u05d3\u05d5\u05d0\"\u05dc"
|
||||
},
|
||||
"title": "\u05d4\u05d6\u05df \u05e9\u05dd \u05de\u05e9\u05ea\u05de\u05e9 \u05d5\u05e1\u05d9\u05e1\u05de\u05d4"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/hu.json
Normal file
19
custom_components/vesync/translations/hu.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "M\u00e1r konfigur\u00e1lva van. Csak egy konfigur\u00e1ci\u00f3 lehets\u00e9ges."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\u00c9rv\u00e9nytelen hiteles\u00edt\u00e9s"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Jelsz\u00f3",
|
||||
"username": "E-mail"
|
||||
},
|
||||
"title": "\u00cdrja be a felhaszn\u00e1l\u00f3nevet \u00e9s a jelsz\u00f3t"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/id.json
Normal file
19
custom_components/vesync/translations/id.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Sudah dikonfigurasi. Hanya satu konfigurasi yang diizinkan."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Autentikasi tidak valid"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Kata Sandi",
|
||||
"username": "Email"
|
||||
},
|
||||
"title": "Masukkan Nama Pengguna dan Kata Sandi"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/it.json
Normal file
19
custom_components/vesync/translations/it.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Gi\u00e0 configurato. \u00c8 possibile una sola configurazione."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Autenticazione non valida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Password",
|
||||
"username": "Email"
|
||||
},
|
||||
"title": "Immettere nome utente e password"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/ja.json
Normal file
19
custom_components/vesync/translations/ja.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002"
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
|
||||
"username": "E\u30e1\u30fc\u30eb"
|
||||
},
|
||||
"title": "\u30e6\u30fc\u30b6\u30fc\u540d\u3068\u30d1\u30b9\u30ef\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/ko.json
Normal file
19
custom_components/vesync/translations/ko.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\uc774\ubbf8 \uad6c\uc131\ub418\uc5c8\uc2b5\ub2c8\ub2e4. \ud558\ub098\uc758 \uc778\uc2a4\ud134\uc2a4\ub9cc \uad6c\uc131\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\uc778\uc99d\uc774 \uc798\ubabb\ub418\uc5c8\uc2b5\ub2c8\ub2e4"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\ube44\ubc00\ubc88\ud638",
|
||||
"username": "\uc774\uba54\uc77c"
|
||||
},
|
||||
"title": "\uc0ac\uc6a9\uc790 \uc774\ub984\uacfc \ube44\ubc00\ubc88\ud638\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/lb.json
Normal file
19
custom_components/vesync/translations/lb.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Scho konfigur\u00e9iert. N\u00ebmmen eng eenzeg Konfiguratioun m\u00e9iglech."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Ong\u00eblteg Authentifikatioun"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Passwuert",
|
||||
"username": "E-Mail"
|
||||
},
|
||||
"title": "Benotzernumm a Passwuert aginn"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
custom_components/vesync/translations/lv.json
Normal file
12
custom_components/vesync/translations/lv.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Parole",
|
||||
"username": "E-pasta adrese"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/nl.json
Normal file
19
custom_components/vesync/translations/nl.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Al geconfigureerd. Slecht \u00e9\u00e9n configuratie mogelijk."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Ongeldige authenticatie"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Wachtwoord",
|
||||
"username": "E-mail"
|
||||
},
|
||||
"title": "Voer gebruikersnaam en wachtwoord in"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/no.json
Normal file
19
custom_components/vesync/translations/no.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Allerede konfigurert. Bare \u00e9n enkelt konfigurasjon er mulig."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Ugyldig godkjenning"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Passord",
|
||||
"username": "E-post"
|
||||
},
|
||||
"title": "Fyll inn brukernavn og passord"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/pl.json
Normal file
19
custom_components/vesync/translations/pl.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Ju\u017c skonfigurowano. Mo\u017cliwa jest tylko jedna konfiguracja."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Niepoprawne uwierzytelnienie"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Has\u0142o",
|
||||
"username": "Adres e-mail"
|
||||
},
|
||||
"title": "Wprowad\u017a nazw\u0119 u\u017cytkownika i has\u0142o."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
12
custom_components/vesync/translations/pt-BR.json
Normal file
12
custom_components/vesync/translations/pt-BR.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"invalid_auth": "Autentica\u00e7\u00e3o invalida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Digite o nome de usu\u00e1rio e a senha"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/pt.json
Normal file
19
custom_components/vesync/translations/pt.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "J\u00e1 configurado. Apenas uma \u00fanica configura\u00e7\u00e3o \u00e9 poss\u00edvel."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Palavra-passe",
|
||||
"username": "Endere\u00e7o de email"
|
||||
},
|
||||
"title": "Introduza o nome de utilizador e a palavra-passe"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/ru.json
Normal file
19
custom_components/vesync/translations/ru.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"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": {
|
||||
"invalid_auth": "\u041e\u0448\u0438\u0431\u043a\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
|
||||
"username": "\u0410\u0434\u0440\u0435\u0441 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b"
|
||||
},
|
||||
"title": "VeSync"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
14
custom_components/vesync/translations/sk.json
Normal file
14
custom_components/vesync/translations/sk.json
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"invalid_auth": "Neplatn\u00e9 overenie"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"username": "Email"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
custom_components/vesync/translations/sl.json
Normal file
13
custom_components/vesync/translations/sl.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Geslo",
|
||||
"username": "E-po\u0161tni naslov"
|
||||
},
|
||||
"title": "Vnesite uporabni\u0161ko Ime in Geslo"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
custom_components/vesync/translations/sv.json
Normal file
13
custom_components/vesync/translations/sv.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "L\u00f6senord",
|
||||
"username": "E-postadress"
|
||||
},
|
||||
"title": "Ange anv\u00e4ndarnamn och l\u00f6senord"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/tr.json
Normal file
19
custom_components/vesync/translations/tr.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "Zaten yap\u0131land\u0131r\u0131lm\u0131\u015f. Yaln\u0131zca tek bir konfig\u00fcrasyon m\u00fcmk\u00fcnd\u00fcr."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "Ge\u00e7ersiz kimlik do\u011frulama"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Parola",
|
||||
"username": "E-posta"
|
||||
},
|
||||
"title": "Kullan\u0131c\u0131 Ad\u0131 ve \u015eifre Girin"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
19
custom_components/vesync/translations/uk.json
Normal file
19
custom_components/vesync/translations/uk.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"single_instance_allowed": "\u041d\u0430\u043b\u0430\u0448\u0442\u0443\u0432\u0430\u043d\u043d\u044f \u0432\u0436\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u043e. \u041c\u043e\u0436\u043d\u0430 \u0434\u043e\u0434\u0430\u0442\u0438 \u043b\u0438\u0448\u0435 \u043e\u0434\u043d\u0443 \u043a\u043e\u043d\u0444\u0456\u0433\u0443\u0440\u0430\u0446\u0456\u044e."
|
||||
},
|
||||
"error": {
|
||||
"invalid_auth": "\u041d\u0435\u0432\u0456\u0440\u043d\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f."
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
|
||||
"username": "\u0410\u0434\u0440\u0435\u0441\u0430 \u0435\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0457 \u043f\u043e\u0448\u0442\u0438"
|
||||
},
|
||||
"title": "VeSync"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user