mirror of
https://github.com/Ladebeze66/tuya_project.git
synced 2025-12-13 09:06:54 +01:00
first commit
This commit is contained in:
commit
5be2ecd2a1
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"commentTranslate.targetLanguage": "fr"
|
||||
}
|
||||
4208
devices.json
Normal file
4208
devices.json
Normal file
File diff suppressed because it is too large
Load Diff
22
scan_wifi.py
Normal file
22
scan_wifi.py
Normal file
@ -0,0 +1,22 @@
|
||||
import tinytuya
|
||||
|
||||
# Créer un objet Cloud avec vos identifiants
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion="eu", # 'eu', 'us', 'cn', selon ton projet
|
||||
apiKey="fdjdjurkm34yyjp77c7d",
|
||||
apiSecret="3e71807fb0c6406792bdf4f07f98e577"
|
||||
)
|
||||
|
||||
# Scanner les appareils
|
||||
print("🔍 Recherche de vos appareils connectés...")
|
||||
|
||||
devices = cloud.getdevices()
|
||||
|
||||
# Afficher tous les appareils trouvés
|
||||
for device in devices:
|
||||
print("="*40)
|
||||
print(f"Nom : {device['name']}")
|
||||
print(f"ID : {device['id']}")
|
||||
print(f"IP : {device.get('ip', 'N/A')}")
|
||||
print(f"LocalKey : {device.get('local_key', 'N/A')}")
|
||||
print("="*40)
|
||||
746
snapshot.json
Normal file
746
snapshot.json
Normal file
@ -0,0 +1,746 @@
|
||||
{
|
||||
"timestamp": 1745608535.9669468,
|
||||
"devices": [
|
||||
{
|
||||
"id": "bf3254180de3bdd7bfnbei",
|
||||
"ip": "192.168.1.179",
|
||||
"uuid": "5ff3703402383ea3",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "uqehhcrmk5depvtl",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "prise caf\u00e9",
|
||||
"key": "5S2Z#]<iwep.PTnB",
|
||||
"mac": "4c:a9:19:35:c0:2a",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": false,
|
||||
"9": 0,
|
||||
"17": 1,
|
||||
"18": 0,
|
||||
"19": 0,
|
||||
"20": 2356,
|
||||
"21": 1,
|
||||
"22": 558,
|
||||
"23": 28500,
|
||||
"24": 15392,
|
||||
"25": 2710,
|
||||
"26": 0,
|
||||
"38": "memory",
|
||||
"39": "relay",
|
||||
"40": false,
|
||||
"41": "",
|
||||
"42": "",
|
||||
"43": "",
|
||||
"51": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bff082745aedf9fc1aqy3e",
|
||||
"ip": "192.168.1.198",
|
||||
"uuid": "197acbff0fa71bc7",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "4pqpkp1rskkjtxay",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "Volet dino",
|
||||
"key": "VXg'ZP9IOI|:N)r:",
|
||||
"mac": "38:a5:c9:1e:da:ad",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": "stop",
|
||||
"8": "forward",
|
||||
"10": 60
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bfc74a089fe0a9a50d2eeg",
|
||||
"ip": "192.168.1.126",
|
||||
"uuid": "022f41ec2cea7aad",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "4pqpkp1rskkjtxay",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "volet salon",
|
||||
"key": "~s0wD/yuq#p}]:]n",
|
||||
"mac": "b8:06:0d:69:a2:2d",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": "stop",
|
||||
"8": "back",
|
||||
"10": 60
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf5b5aa8312d543135xxak",
|
||||
"ip": "192.168.1.61",
|
||||
"uuid": "454132f7cf43daaf",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "4pqpkp1rskkjtxay",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "volet delia",
|
||||
"key": "Hj1MO4C)5TL)qndh",
|
||||
"mac": "d8:d6:68:c0:ef:8c",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": "stop",
|
||||
"8": "forward",
|
||||
"10": 60
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "820180048cce4e2aecc7",
|
||||
"ip": "192.168.1.160",
|
||||
"active": 2,
|
||||
"ability": 0,
|
||||
"mode": 0,
|
||||
"encrypt": true,
|
||||
"productKey": "tsbguim4trl6fa7g",
|
||||
"name": "bureau dino",
|
||||
"key": "_rgNtA^X&Vp)A|^l",
|
||||
"mac": "8c:ce:4e:2a:ec:c7",
|
||||
"token": "",
|
||||
"wf_cfg": "",
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"devId": "820180048cce4e2aecc7",
|
||||
"dps": {
|
||||
"1": true,
|
||||
"2": true,
|
||||
"3": true,
|
||||
"7": false,
|
||||
"9": 0,
|
||||
"10": 0,
|
||||
"11": 0,
|
||||
"15": 0,
|
||||
"18": 788,
|
||||
"19": 1809,
|
||||
"20": 2293,
|
||||
"101": false,
|
||||
"102": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.3"
|
||||
},
|
||||
{
|
||||
"id": "bf81367b1f5c267af7yyht",
|
||||
"ip": "192.168.1.118",
|
||||
"uuid": "89a27ed28f171442",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "4pqpkp1rskkjtxay",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "volet cuisine",
|
||||
"key": "9l{9^IYi}CT63k.b",
|
||||
"mac": "d8:d6:68:c0:f1:c5",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": "stop",
|
||||
"8": "forward",
|
||||
"10": 60
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf0e197f469e9f2670fb27",
|
||||
"ip": "192.168.1.20",
|
||||
"uuid": "7b42b4575e8aa241",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "4pqpkp1rskkjtxay",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"sl": 0,
|
||||
"clientLink": 3,
|
||||
"name": "volet jean luc",
|
||||
"key": "j$doVJIPumHd2PUf",
|
||||
"mac": "b8:06:0d:69:a8:8b",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": "stop",
|
||||
"8": "back",
|
||||
"10": 60
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf5516c52504a7a8dcof7r",
|
||||
"ip": "192.168.1.54",
|
||||
"uuid": "ea51f80ebfc154f7",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "key8u54q9dtru5jw",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "light 2",
|
||||
"key": "|iyOE'];IEiaQ7}l",
|
||||
"mac": "d8:d6:68:88:56:9d",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": false,
|
||||
"21": "white",
|
||||
"22": 100,
|
||||
"23": 200,
|
||||
"24": "003c03e803e8",
|
||||
"25": "07464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000",
|
||||
"26": 0
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bfdc2f8e4effa0d826gnxg",
|
||||
"ip": "192.168.1.138",
|
||||
"uuid": "ac759c73d50d90cd",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "key8u54q9dtru5jw",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "Light 1",
|
||||
"key": "a_8Bhm|P1L;{wCHL",
|
||||
"mac": "d8:d6:68:88:60:28",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": false,
|
||||
"21": "white",
|
||||
"22": 100,
|
||||
"23": 200,
|
||||
"24": "003c03e803e8",
|
||||
"25": "07464602000003e803e800000000464602007803e803e80000000046460200f003e803e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e800000000",
|
||||
"26": 0
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf4054de281cb6ada8actg",
|
||||
"ip": "192.168.1.149",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "d7bwplp3edtnkxxh",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "Sir\u00e8ne intelligente",
|
||||
"key": "HokvwP_PM{r#SIHb",
|
||||
"mac": "4c:a9:19:01:08:14",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"105": 180,
|
||||
"106": true,
|
||||
"116": "Disarm_",
|
||||
"117": "0",
|
||||
"118": "0",
|
||||
"120": "3",
|
||||
"121": true,
|
||||
"127": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bfd5eb950aecda95d3mgpq",
|
||||
"ip": "192.168.1.53",
|
||||
"uuid": "71be6e7cdc78dcde",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keynremrcjf97twe",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "bambulight",
|
||||
"key": "R=_N.r9`clUY!JKA",
|
||||
"mac": "f8:17:2d:75:a4:f4",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": false,
|
||||
"21": "white",
|
||||
"22": 1000,
|
||||
"25": "000e0d0000000000000000c803e8",
|
||||
"26": 0,
|
||||
"34": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf2765002c5c1bcf1e4vcl",
|
||||
"ip": "192.168.1.28",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "key5ckdnys3pqgec",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "salon",
|
||||
"key": "d_gEbC>@_d:0F{bV",
|
||||
"mac": "4c:a9:19:68:7f:bb",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": false,
|
||||
"2": true,
|
||||
"7": 0,
|
||||
"8": 0,
|
||||
"14": "memory",
|
||||
"16": true,
|
||||
"17": "",
|
||||
"18": "",
|
||||
"19": ""
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bfca435612874e22ecfqa0",
|
||||
"ip": "192.168.1.115",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "gaobbrxqiblcng2p",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "Light tv",
|
||||
"key": "Nei5]1k?GzT)c]ZM",
|
||||
"mac": "c4:82:e1:de:b1:4a",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"101": "film_mode",
|
||||
"102": false,
|
||||
"103": 1,
|
||||
"104": 100,
|
||||
"105": 0,
|
||||
"108": 64,
|
||||
"111": "0000ff",
|
||||
"112": 100,
|
||||
"113": 5,
|
||||
"114": 100,
|
||||
"115": false,
|
||||
"116": 12,
|
||||
"117": 7,
|
||||
"118": 200,
|
||||
"119": 200,
|
||||
"120": 0,
|
||||
"122": "ffffff",
|
||||
"125": "BRG",
|
||||
"126": true,
|
||||
"127": "RD200 _HDMI2.0_240109 V08.08.08.3840*2160P 60Hz36bitYCbCr420.CS 27. 27.296M.HDR.2200.2250. 148. 072.1.1921.1079.0.hdcp22.led 38."
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bf06f9007abca55618iiwv",
|
||||
"ip": "192.168.1.68",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keyjnuy4s3kre7m7",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "SW2",
|
||||
"key": "fkkV`gX-@(}H.0U=",
|
||||
"mac": "b8:06:0d:28:c1:93",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": false,
|
||||
"9": 0,
|
||||
"20": 1,
|
||||
"21": 0,
|
||||
"22": 0,
|
||||
"23": 2333,
|
||||
"24": 1,
|
||||
"29": 0,
|
||||
"38": "memory",
|
||||
"42": "",
|
||||
"43": "",
|
||||
"44": "AAAC"
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bfc369d2ca89602058xajc",
|
||||
"ip": "192.168.1.13",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keyjup78v54myhan",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "ecran gauche",
|
||||
"key": "+/l==gS<gkhbF(}0",
|
||||
"mac": "d8:d6:68:89:38:d4",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": true,
|
||||
"9": 0,
|
||||
"17": 18,
|
||||
"18": 272,
|
||||
"19": 361,
|
||||
"20": 2306,
|
||||
"21": 1,
|
||||
"22": 563,
|
||||
"23": 27351,
|
||||
"24": 14750,
|
||||
"25": 2820,
|
||||
"26": 0,
|
||||
"38": "memory",
|
||||
"39": false,
|
||||
"41": false,
|
||||
"42": "",
|
||||
"43": "",
|
||||
"44": ""
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bfadb5f27d0fe9a778ixwc",
|
||||
"ip": "192.168.1.70",
|
||||
"uuid": "3c52e36d800e6c9c",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keynremrcjf97twe",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "ringlight",
|
||||
"key": "dOo5*OR3ixjP?OxO",
|
||||
"mac": "f8:17:2d:6f:72:55",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": true,
|
||||
"21": "white",
|
||||
"22": 1000,
|
||||
"25": "000e0d0000000000000000c803e8",
|
||||
"26": 0,
|
||||
"34": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf9043f5954449c435mcec",
|
||||
"ip": "192.168.1.92",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keyjup78v54myhan",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "imprimante 3d",
|
||||
"key": "t0o#ih7L!$;+6R(2",
|
||||
"mac": "b8:06:0d:fb:a8:1b",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": true,
|
||||
"9": 0,
|
||||
"17": 49,
|
||||
"18": 307,
|
||||
"19": 352,
|
||||
"20": 2341,
|
||||
"21": 1,
|
||||
"22": 578,
|
||||
"23": 28444,
|
||||
"24": 15476,
|
||||
"25": 2690,
|
||||
"26": 0,
|
||||
"38": "memory",
|
||||
"39": true,
|
||||
"41": false,
|
||||
"42": "",
|
||||
"43": "",
|
||||
"44": ""
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bf10d8832c8447c512jedz",
|
||||
"ip": "192.168.1.8",
|
||||
"uuid": "60c8aec31f22286a",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keynremrcjf97twe",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "windowled",
|
||||
"key": "e#Z$#dvgmRo}nS8^",
|
||||
"mac": "f8:17:2d:cd:24:f7",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": false,
|
||||
"21": "colour",
|
||||
"24": "00b403e803e8",
|
||||
"25": "1a464602000a038403e800000000464602000003e803e800000000",
|
||||
"26": 0,
|
||||
"34": false,
|
||||
"42": "010000016432000003e8007803e800f003e8003c03e800b403e8012c03e8"
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bfe57aa0e61a9b529bzrff",
|
||||
"ip": "192.168.1.128",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "rtbhfbuii82scjrp",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "PC",
|
||||
"key": "|fI8f~QH~5>>m0x?",
|
||||
"mac": "b8:06:0d:3e:79:77",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": true,
|
||||
"7": false,
|
||||
"8": true,
|
||||
"38": "off",
|
||||
"40": false,
|
||||
"101": "0",
|
||||
"102": "off"
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bff3ca58c60d8b18d4x3dn",
|
||||
"ip": "192.168.1.122",
|
||||
"uuid": "f95b88cfd4065f4d",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keynremrcjf97twe",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"clientLink": 3,
|
||||
"name": "chinalight",
|
||||
"key": "Nt6*~S4<2x9;?Q+-",
|
||||
"mac": "f8:17:2d:6f:66:89",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"20": false,
|
||||
"21": "white",
|
||||
"22": 1000,
|
||||
"25": "000e0d0000000000000000c803e8",
|
||||
"26": 0,
|
||||
"34": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.5"
|
||||
},
|
||||
{
|
||||
"id": "bf81674a39ad0f61f4tzjt",
|
||||
"ip": "192.168.1.99",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "keyjup78v54myhan",
|
||||
"token": true,
|
||||
"wf_cfg": true,
|
||||
"name": "Bureau",
|
||||
"key": "~@d`/>iCON6aPp~@",
|
||||
"mac": "d8:d6:68:87:07:6a",
|
||||
"ability": 0,
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"1": true,
|
||||
"9": 0,
|
||||
"17": 27,
|
||||
"18": 417,
|
||||
"19": 546,
|
||||
"20": 2294,
|
||||
"21": 1,
|
||||
"22": 557,
|
||||
"23": 26736,
|
||||
"24": 14371,
|
||||
"25": 2900,
|
||||
"26": 0,
|
||||
"38": "memory",
|
||||
"39": false,
|
||||
"41": false,
|
||||
"42": "",
|
||||
"43": "",
|
||||
"44": ""
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.4"
|
||||
},
|
||||
{
|
||||
"id": "bf584a5db6d2208dcf2bol",
|
||||
"ip": "192.168.1.80",
|
||||
"active": 2,
|
||||
"encrypt": true,
|
||||
"productKey": "biw8urjw2dvss3ur",
|
||||
"token": true,
|
||||
"name": "Cam-Dino",
|
||||
"key": "mAF-Jj#O.#0@Lk?[",
|
||||
"mac": "c5:92:42:1a:13:79",
|
||||
"ability": 0,
|
||||
"wf_cfg": "",
|
||||
"dev_type": "default",
|
||||
"err": "",
|
||||
"type": "default",
|
||||
"dps": {
|
||||
"dps": {
|
||||
"101": true,
|
||||
"103": false,
|
||||
"104": true,
|
||||
"105": false,
|
||||
"106": "1",
|
||||
"108": "0",
|
||||
"109": "61038592|48714752|12323840",
|
||||
"110": 1,
|
||||
"117": 0,
|
||||
"120": false,
|
||||
"134": false,
|
||||
"139": false,
|
||||
"140": "0",
|
||||
"150": true,
|
||||
"151": "2",
|
||||
"159": false,
|
||||
"160": 10,
|
||||
"161": false,
|
||||
"168": false,
|
||||
"169": "",
|
||||
"170": false,
|
||||
"174": false,
|
||||
"175": "0",
|
||||
"176": "0",
|
||||
"188": "0",
|
||||
"194": 20,
|
||||
"195": 50,
|
||||
"237": false,
|
||||
"239": false
|
||||
}
|
||||
},
|
||||
"origin": "broadcast",
|
||||
"ver": "3.3"
|
||||
}
|
||||
]
|
||||
}
|
||||
6
tinytuya.json
Normal file
6
tinytuya.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"apiKey": "fdjdjurkm34yyjp77c7d",
|
||||
"apiSecret": "3e71807fb0c6406792bdf4f07f98e577",
|
||||
"apiRegion": "eu",
|
||||
"apiDeviceID": "scan"
|
||||
}
|
||||
83
tuya-control/README.md
Normal file
83
tuya-control/README.md
Normal file
@ -0,0 +1,83 @@
|
||||
# Tuya Control pour StreamDeck
|
||||
|
||||
Ce projet permet de contrôler vos appareils Tuya (prises, lumières, volets, etc.) via des scripts Python, conçus pour être utilisés avec un StreamDeck.
|
||||
|
||||
## Structure du projet
|
||||
|
||||
```
|
||||
tuya-control/
|
||||
├── common/ # Fonctions utilitaires communes
|
||||
│ ├── utils.py # Fonctions partagées
|
||||
│ └── config.py # Configuration générale
|
||||
├── devices/ # Scripts spécifiques par type d'appareil
|
||||
│ ├── lights/ # Contrôle des lumières
|
||||
│ ├── shutters/ # Contrôle des volets
|
||||
│ ├── plugs/ # Contrôle des prises
|
||||
│ ├── cameras/ # Contrôle des caméras
|
||||
│ └── others/ # Autres types d'appareils
|
||||
├── scripts/ # Scripts utilitaires
|
||||
│ ├── scan_devices.py # Scanner les appareils sur le réseau
|
||||
│ └── status_devices.py # Afficher le statut des appareils
|
||||
├── devices.json # Base de données des appareils
|
||||
└── README.md # Ce fichier
|
||||
```
|
||||
|
||||
## Configuration du StreamDeck
|
||||
|
||||
Pour utiliser ces scripts avec votre StreamDeck:
|
||||
|
||||
1. Configurez une touche sur votre StreamDeck pour exécuter un script Python
|
||||
2. Pointez vers le script correspondant à l'appareil que vous souhaitez contrôler
|
||||
(ex: `tuya-control/devices/lights/light_1_toggle.py`)
|
||||
3. Définissez une icône appropriée pour l'état ON/OFF
|
||||
|
||||
Chaque script gère automatiquement la détection de l'état actuel et bascule entre allumé/éteint ou ouvert/fermé/arrêté selon le type d'appareil.
|
||||
|
||||
## Exemples d'utilisation
|
||||
|
||||
### Contrôler une prise
|
||||
```bash
|
||||
python tuya-control/devices/plugs/prise_cafe_toggle.py
|
||||
```
|
||||
|
||||
### Contrôler un volet
|
||||
```bash
|
||||
python tuya-control/devices/shutters/volet_salon_toggle.py
|
||||
```
|
||||
|
||||
### Contrôler une lumière
|
||||
```bash
|
||||
python tuya-control/devices/lights/light_1_toggle.py
|
||||
```
|
||||
|
||||
### Scanner les appareils sur le réseau
|
||||
```bash
|
||||
python tuya-control/scripts/scan_devices.py
|
||||
```
|
||||
|
||||
### Afficher le statut des appareils
|
||||
```bash
|
||||
python tuya-control/scripts/status_devices.py
|
||||
```
|
||||
|
||||
## Personnalisation
|
||||
|
||||
Pour ajouter ou modifier des appareils, il suffit de copier un script existant et d'adapter:
|
||||
- L'ID de l'appareil
|
||||
- Le nom de l'appareil
|
||||
- Le type de commande (DPS) spécifique à l'appareil
|
||||
|
||||
## Dépendances
|
||||
|
||||
Ce projet nécessite:
|
||||
- Python 3.6+
|
||||
- La bibliothèque tinytuya
|
||||
|
||||
Pour installer les dépendances:
|
||||
```bash
|
||||
pip install tinytuya
|
||||
```
|
||||
|
||||
## Remarques
|
||||
|
||||
Pour que les scripts fonctionnent, le fichier `devices.json` doit contenir les informations de connexion pour tous vos appareils, incluant les clés locales.
|
||||
BIN
tuya-control/common/__pycache__/config.cpython-313.pyc
Normal file
BIN
tuya-control/common/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
BIN
tuya-control/common/__pycache__/utils.cpython-313.pyc
Normal file
BIN
tuya-control/common/__pycache__/utils.cpython-313.pyc
Normal file
Binary file not shown.
24
tuya-control/common/config.py
Normal file
24
tuya-control/common/config.py
Normal file
@ -0,0 +1,24 @@
|
||||
"""
|
||||
Configuration pour l'accès à l'API Tuya.
|
||||
Ce fichier centralise les informations de connexion pour tous les scripts.
|
||||
"""
|
||||
|
||||
# Informations de l'API Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Mode de connexion - 'scan', 'local', ou 'both'
|
||||
CONNECTION_MODE = "local" # Privilégier la connexion locale pour plus de rapidité
|
||||
|
||||
# Délai d'attente en secondes pour les opérations réseau
|
||||
TIMEOUT = 3.0
|
||||
|
||||
# Gestion des voyants sur les appareils
|
||||
DISABLE_STATUS_LED = False # True = désactiver les LEDs des appareils (si supporté)
|
||||
|
||||
# Configuration du mode verbose
|
||||
VERBOSE_MODE = True # Afficher plus d'informations pendant l'exécution
|
||||
|
||||
# Préfixe pour l'intégration avec StreamDeck
|
||||
STREAMDECK_PREFIX = "TUYA_" # Préfixe pour les variables d'environnement
|
||||
257
tuya-control/common/utils.py
Normal file
257
tuya-control/common/utils.py
Normal file
@ -0,0 +1,257 @@
|
||||
"""
|
||||
Utilitaires partagés pour les scripts de contrôle des appareils Tuya.
|
||||
Ce module fournit des fonctions communes utilisées par tous les scripts.
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import logging
|
||||
import tinytuya
|
||||
from . import config
|
||||
|
||||
# Configuration du logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO if config.VERBOSE_MODE else logging.WARNING,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
||||
handlers=[logging.StreamHandler()]
|
||||
)
|
||||
logger = logging.getLogger("TuyaControl")
|
||||
|
||||
def load_device_info(device_id):
|
||||
"""
|
||||
Charge les informations d'un appareil depuis le fichier devices.json
|
||||
|
||||
Args:
|
||||
device_id (str): ID de l'appareil Tuya
|
||||
|
||||
Returns:
|
||||
dict: Informations de l'appareil ou None si non trouvé
|
||||
"""
|
||||
try:
|
||||
# Chemin vers le répertoire parent du projet
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
devices_file = os.path.join(base_dir, 'devices.json')
|
||||
|
||||
with open(devices_file, 'r') as f:
|
||||
devices = json.load(f)
|
||||
|
||||
for device in devices:
|
||||
if device['id'] == device_id:
|
||||
return device
|
||||
|
||||
logger.error(f"Appareil avec ID {device_id} non trouvé dans devices.json")
|
||||
return None
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors du chargement des informations de l'appareil: {e}")
|
||||
return None
|
||||
|
||||
def connect_device(device_id, device_ip=None, device_key=None, device_version=3.3):
|
||||
"""
|
||||
Se connecte à un appareil Tuya
|
||||
|
||||
Args:
|
||||
device_id (str): ID de l'appareil
|
||||
device_ip (str, optional): IP de l'appareil (facultatif si mode scan)
|
||||
device_key (str, optional): Clé de l'appareil (facultatif si chargé depuis devices.json)
|
||||
device_version (float, optional): Version du protocole
|
||||
|
||||
Returns:
|
||||
tinytuya.Device: Instance de l'appareil connecté ou None en cas d'erreur
|
||||
"""
|
||||
try:
|
||||
# Si la clé n'est pas fournie, charger depuis devices.json
|
||||
if device_key is None:
|
||||
device_info = load_device_info(device_id)
|
||||
if not device_info:
|
||||
logger.error(f"Impossible de trouver les informations pour l'appareil {device_id}")
|
||||
return None
|
||||
device_key = device_info.get('key')
|
||||
|
||||
# Créer l'objet appareil
|
||||
device = tinytuya.Device(
|
||||
dev_id=device_id,
|
||||
address=device_ip, # None si on veut que la bibliothèque recherche l'appareil
|
||||
local_key=device_key,
|
||||
version=device_version
|
||||
)
|
||||
|
||||
# Configurer le timeout
|
||||
device.set_socketTimeout(config.TIMEOUT)
|
||||
|
||||
# Tester la connexion
|
||||
status = device.status()
|
||||
if 'Error' in status:
|
||||
logger.error(f"Erreur de connexion à l'appareil {device_id}: {status['Error']}")
|
||||
return None
|
||||
|
||||
logger.info(f"Connexion réussie à l'appareil {device_id}")
|
||||
return device
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la connexion à l'appareil {device_id}: {e}")
|
||||
return None
|
||||
|
||||
def toggle_device(device, switch_id="1", current_state=None):
|
||||
"""
|
||||
Bascule l'état d'un appareil (allumé/éteint)
|
||||
|
||||
Args:
|
||||
device (tinytuya.Device): Instance de l'appareil
|
||||
switch_id (str): ID du commutateur (généralement "1" ou "20" pour les lumières)
|
||||
current_state (bool, optional): État actuel si connu, sinon sera détecté
|
||||
|
||||
Returns:
|
||||
bool: Nouvel état (True=On, False=Off) ou None en cas d'erreur
|
||||
"""
|
||||
try:
|
||||
# Si l'état actuel n'est pas fourni, l'obtenir
|
||||
if current_state is None:
|
||||
status = device.status()
|
||||
if 'dps' in status and switch_id in status['dps']:
|
||||
current_state = status['dps'][switch_id]
|
||||
else:
|
||||
logger.error(f"Impossible de déterminer l'état actuel du commutateur {switch_id}")
|
||||
return None
|
||||
|
||||
# Basculer l'état (inverse de l'état actuel)
|
||||
new_state = not current_state
|
||||
result = device.set_value(switch_id, new_state)
|
||||
|
||||
logger.info(f"Appareil basculé de {current_state} à {new_state}")
|
||||
return new_state
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors du basculement de l'appareil: {e}")
|
||||
return None
|
||||
|
||||
def control_shutter(device, action="stop"):
|
||||
"""
|
||||
Contrôle un volet roulant ou store
|
||||
|
||||
Args:
|
||||
device (tinytuya.Device): Instance de l'appareil
|
||||
action (str): Action à effectuer ("stop", "up"/"forward", "down"/"back")
|
||||
|
||||
Returns:
|
||||
bool: True si réussi, False sinon
|
||||
"""
|
||||
try:
|
||||
# Convertir les actions en commandes spécifiques au dispositif
|
||||
command = action
|
||||
if action == "up":
|
||||
command = "forward"
|
||||
elif action == "down":
|
||||
command = "back"
|
||||
|
||||
# Les volets utilisent généralement le point de données "1" pour leurs commandes
|
||||
result = device.set_value("1", command)
|
||||
|
||||
logger.info(f"Volet contrôlé avec commande: {command}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors du contrôle du volet: {e}")
|
||||
return False
|
||||
|
||||
def get_device_status_text(device_id, status=None):
|
||||
"""
|
||||
Obtient un texte descriptif de l'état de l'appareil
|
||||
|
||||
Args:
|
||||
device_id (str): ID de l'appareil
|
||||
status (dict, optional): État actuel si déjà obtenu
|
||||
|
||||
Returns:
|
||||
str: Description textuelle de l'état
|
||||
"""
|
||||
try:
|
||||
device_info = load_device_info(device_id)
|
||||
if not device_info:
|
||||
return "Appareil inconnu"
|
||||
|
||||
# Si le statut n'est pas fourni, essayer de se connecter et obtenir l'état
|
||||
if status is None:
|
||||
device = connect_device(device_id)
|
||||
if device:
|
||||
status = device.status()
|
||||
else:
|
||||
return "Non connecté"
|
||||
|
||||
# Obtenir le nom de l'appareil
|
||||
device_name = device_info.get('name', 'Appareil')
|
||||
|
||||
# Analyser l'état selon le type d'appareil
|
||||
if 'dps' in status:
|
||||
dps = status['dps']
|
||||
|
||||
# Pour les prises et la plupart des appareils on/off
|
||||
if '1' in dps and isinstance(dps['1'], bool):
|
||||
state = "ALLUMÉ" if dps['1'] else "ÉTEINT"
|
||||
return f"{device_name}: {state}"
|
||||
|
||||
# Pour les lumières (généralement dps 20)
|
||||
elif '20' in dps and isinstance(dps['20'], bool):
|
||||
state = "ALLUMÉE" if dps['20'] else "ÉTEINTE"
|
||||
return f"{device_name}: {state}"
|
||||
|
||||
# Pour les volets
|
||||
elif '1' in dps and isinstance(dps['1'], str):
|
||||
states = {
|
||||
"stop": "ARRÊTÉ",
|
||||
"forward": "EN OUVERTURE",
|
||||
"back": "EN FERMETURE"
|
||||
}
|
||||
state = states.get(dps['1'], dps['1'].upper())
|
||||
return f"{device_name}: {state}"
|
||||
|
||||
return f"{device_name}: État inconnu"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de l'obtention de l'état de l'appareil: {e}")
|
||||
return "Erreur"
|
||||
|
||||
def scan_for_devices():
|
||||
"""
|
||||
Recherche les appareils Tuya disponibles sur le réseau local
|
||||
|
||||
Returns:
|
||||
list: Liste des appareils trouvés
|
||||
"""
|
||||
try:
|
||||
logger.info("Recherche des appareils Tuya sur le réseau...")
|
||||
devices = tinytuya.scan()
|
||||
if devices is None:
|
||||
devices = []
|
||||
logger.info(f"Trouvé {len(devices)} appareils")
|
||||
return devices
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la recherche d'appareils: {e}")
|
||||
return []
|
||||
|
||||
# Fonction pour l'intégration avec StreamDeck
|
||||
def report_for_streamdeck(result, device_name="Appareil", new_state=None):
|
||||
"""
|
||||
Génère un rapport formaté pour l'intégration avec StreamDeck
|
||||
|
||||
Args:
|
||||
result (bool): Résultat de l'opération
|
||||
device_name (str): Nom de l'appareil
|
||||
new_state: Nouvel état (True=On, False=Off, str pour d'autres états)
|
||||
|
||||
Returns:
|
||||
dict: Rapport formaté
|
||||
"""
|
||||
# Format attendu par StreamDeck
|
||||
report = {
|
||||
"success": result is not None and result is not False,
|
||||
"device": device_name,
|
||||
"state": str(new_state) if new_state is not None else "unknown",
|
||||
"timestamp": time.time()
|
||||
}
|
||||
|
||||
# Afficher le rapport au format JSON pour StreamDeck
|
||||
print(json.dumps(report))
|
||||
return report
|
||||
37
tuya-control/devices/cameras/cam_dino_toggle.py
Normal file
37
tuya-control/devices/cameras/cam_dino_toggle.py
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de la caméra (activé/désactivé)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf584a5db6d2208dcf2bol"
|
||||
DEVICE_NAME = "Cam-Dino"
|
||||
|
||||
# Pour cette caméra, le commutateur principal est sur le DPS 101
|
||||
SWITCH_ID = "101"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état de la caméra"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device, SWITCH_ID)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
161
tuya-control/devices/lights/all_lights_effects_toggle.py
Normal file
161
tuya-control/devices/lights/all_lights_effects_toggle.py
Normal file
@ -0,0 +1,161 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de plusieurs lumières d'ambiance simultanément:
|
||||
- Saber du bureau dino
|
||||
- Ringlight
|
||||
- Chinalight
|
||||
- Windowled
|
||||
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import tinytuya
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import report_for_streamdeck
|
||||
from common import config
|
||||
|
||||
# Obtenir le logger
|
||||
logger = logging.getLogger("TuyaControl")
|
||||
|
||||
# ID et paramètres des appareils
|
||||
DEVICES = [
|
||||
{
|
||||
"id": "820180048cce4e2aecc7",
|
||||
"name": "Saber (Bureau Dino)",
|
||||
"switch": "7", # Code pour la prise USB (saber)
|
||||
"ip": "192.168.1.160",
|
||||
"key": "_rgNtA^X&Vp)A|^l",
|
||||
"version": 3.3
|
||||
},
|
||||
{
|
||||
"id": "bfadb5f27d0fe9a778ixwc",
|
||||
"name": "Ringlight",
|
||||
"switch": "20",
|
||||
"ip": "192.168.1.70",
|
||||
"key": "dOo5*OR3ixjP?OxO",
|
||||
"version": 3.5
|
||||
},
|
||||
{
|
||||
"id": "bff3ca58c60d8b18d4x3dn",
|
||||
"name": "Chinalight",
|
||||
"switch": "20",
|
||||
"ip": "192.168.1.122",
|
||||
"key": "Nt6*~S4<2x9;?Q+-",
|
||||
"version": 3.5
|
||||
},
|
||||
{
|
||||
"id": "bf10d8832c8447c512jedz",
|
||||
"name": "Windowled",
|
||||
"switch": "20",
|
||||
"ip": "192.168.1.8",
|
||||
"key": "e#Z$#dvgmRo}nS8^",
|
||||
"version": 3.5
|
||||
}
|
||||
]
|
||||
|
||||
def connect_device_direct(device_info):
|
||||
"""
|
||||
Se connecte directement à un appareil avec son IP sans passer par la découverte
|
||||
"""
|
||||
try:
|
||||
# Créer l'objet appareil
|
||||
device = tinytuya.Device(
|
||||
dev_id=device_info["id"],
|
||||
address=device_info["ip"],
|
||||
local_key=device_info["key"],
|
||||
version=device_info["version"]
|
||||
)
|
||||
|
||||
# Configurer le timeout
|
||||
device.set_socketTimeout(config.TIMEOUT)
|
||||
|
||||
# Vérifier la connexion (optionnel)
|
||||
status = device.status()
|
||||
if 'Error' in status:
|
||||
logger.error(f"Erreur de connexion à {device_info['name']} ({device_info['ip']}): {status['Error']}")
|
||||
return None
|
||||
|
||||
logger.info(f"Connexion réussie à {device_info['name']} ({device_info['ip']})")
|
||||
return device
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la connexion à {device_info['name']} ({device_info['ip']}): {e}")
|
||||
return None
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état des lumières d'ambiance simultanément"""
|
||||
# Connexion aux appareils
|
||||
connected_devices = []
|
||||
|
||||
for device_info in DEVICES:
|
||||
try:
|
||||
# Ajouter un petit délai entre chaque connexion pour éviter les collisions de socket
|
||||
time.sleep(0.5)
|
||||
# Connexion directe avec l'IP
|
||||
device = connect_device_direct(device_info)
|
||||
if device:
|
||||
connected_devices.append({
|
||||
"device": device,
|
||||
"name": device_info["name"],
|
||||
"switch": device_info["switch"]
|
||||
})
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur de connexion à {device_info['name']}: {e}")
|
||||
|
||||
if not connected_devices:
|
||||
report_for_streamdeck(False, "Ambiance")
|
||||
return
|
||||
|
||||
try:
|
||||
# Déterminer l'état actuel pour décider de la nouvelle action
|
||||
lights_on = False
|
||||
|
||||
for device_data in connected_devices:
|
||||
try:
|
||||
status = device_data["device"].status()
|
||||
if status.get('dps', {}).get(device_data["switch"], False):
|
||||
lights_on = True
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur lors de la récupération du statut de {device_data['name']}: {e}")
|
||||
|
||||
# Définir le nouvel état (inverse de l'état actuel)
|
||||
new_state = not lights_on
|
||||
|
||||
# Appliquer l'action sur tous les appareils
|
||||
success = True
|
||||
for device_data in connected_devices:
|
||||
try:
|
||||
result = device_data["device"].set_value(device_data["switch"], new_state)
|
||||
if result is None or "Error" in str(result):
|
||||
success = False
|
||||
logger.error(f"Erreur lors du changement d'état de {device_data['name']}")
|
||||
# Ajouter un petit délai entre chaque commande
|
||||
time.sleep(0.2)
|
||||
except Exception as e:
|
||||
success = False
|
||||
logger.error(f"Erreur lors du changement d'état de {device_data['name']}: {e}")
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(success, "Ambiance", new_state)
|
||||
|
||||
finally:
|
||||
# Fermer explicitement toutes les connexions
|
||||
for device_data in connected_devices:
|
||||
try:
|
||||
device_data["device"].set_socketRetryLimit(0)
|
||||
device_data["device"].set_socketTimeout(1)
|
||||
if hasattr(device_data["device"], "_connection") and device_data["device"]._connection:
|
||||
device_data["device"]._connection.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/bambulights.py
Normal file
92
tuya-control/devices/lights/bambulights.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bfd5eb950aecda95d3mgpq" # ID de bambulight
|
||||
DEVICE_NAME = "bambulight"
|
||||
SWITCH_CODE = "switch_led" # Utiliser le code correct pour l'interrupteur
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/bureau_dino_saber_toggle.py
Normal file
92
tuya-control/devices/lights/bureau_dino_saber_toggle.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "820180048cce4e2aecc7" # ID du bureau dino
|
||||
DEVICE_NAME = "Saber (Bureau Dino)"
|
||||
SWITCH_CODE = "switch_usb1" # Code pour la prise USB (saber)
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/chinalight.py
Normal file
92
tuya-control/devices/lights/chinalight.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bff3ca58c60d8b18d4x3dn" # ID de chinalight
|
||||
DEVICE_NAME = "chinalight"
|
||||
SWITCH_CODE = "switch_led" # Utiliser le code correct pour l'interrupteur
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
108
tuya-control/devices/lights/light_1_toggle.py
Normal file
108
tuya-control/devices/lights/light_1_toggle.py
Normal file
@ -0,0 +1,108 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bfdc2f8e4effa0d826gnxg"
|
||||
DEVICE_NAME = "Light 1"
|
||||
SWITCH_CODE = "switch_led" # ou "switch" ou "switch_led", dépend du device (à vérifier !)
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
# Format: {"result": [{"code": "switch_led", "value": true}, ...]}
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
# Format: {"result": {"status": [{"code": "switch_led", "value": true}, ...]}}
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
# Format alternatif: liste directe de statuts
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
|
||||
# Afficher les codes disponibles
|
||||
codes = []
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
codes = [item.get("code") for item in result if isinstance(item, dict) and "code" in item]
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
codes = [item.get("code") for item in result["status"] if isinstance(item, dict) and "code" in item]
|
||||
elif isinstance(status, list):
|
||||
codes = [item.get("code") for item in status if isinstance(item, dict) and "code" in item]
|
||||
|
||||
print(f"💡 Codes disponibles: {codes}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
95
tuya-control/devices/lights/light_2_toggle.py
Normal file
95
tuya-control/devices/lights/light_2_toggle.py
Normal file
@ -0,0 +1,95 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bf5516c52504a7a8dcof7r"
|
||||
DEVICE_NAME = "Light 2"
|
||||
SWITCH_CODE = "switch_led" # ou "switch" ou "switch_led", dépend du device (à vérifier !)
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
# Format: {"result": [{"code": "switch_led", "value": true}, ...]}
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
# Format: {"result": {"status": [{"code": "switch_led", "value": true}, ...]}}
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
# Format alternatif: liste directe de statuts
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
106
tuya-control/devices/lights/light_dino_2.py
Normal file
106
tuya-control/devices/lights/light_dino_2.py
Normal file
@ -0,0 +1,106 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations des appareils
|
||||
DEVICES = [
|
||||
{
|
||||
"id": "bfdc2f8e4effa0d826gnxg", # ID de la lumière 1
|
||||
"name": "Light 1",
|
||||
"switch_code": "switch_led"
|
||||
},
|
||||
{
|
||||
"id": "bf5516c52504a7a8dcof7r", # ID de la lumière 2
|
||||
"name": "Light 2",
|
||||
"switch_code": "switch_led"
|
||||
}
|
||||
]
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
for device in DEVICES:
|
||||
device_id = device["id"]
|
||||
device_name = device["name"]
|
||||
switch_code = device["switch_code"]
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {device_id}...")
|
||||
status = cloud.getstatus(device_id)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {device_name}")
|
||||
continue
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == switch_code:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == switch_code:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == switch_code:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{switch_code}' pour {device_name}")
|
||||
continue
|
||||
|
||||
print(f"ℹ️ État actuel de {device_name}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": switch_code, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(device_id, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {device_name} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {device_name}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/ringlight_toggle.py
Normal file
92
tuya-control/devices/lights/ringlight_toggle.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bfadb5f27d0fe9a778ixwc" # ID de la ringlight
|
||||
DEVICE_NAME = "ringlight"
|
||||
SWITCH_CODE = "switch_led" # Utiliser le code correct pour l'interrupteur
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/salon.py
Normal file
92
tuya-control/devices/lights/salon.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bf2765002c5c1bcf1e4vcl" # ID du salon
|
||||
DEVICE_NAME = "salon"
|
||||
SWITCH_CODE = "switch_1" # Utiliser le code correct pour l'interrupteur 1
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/lights/windowled.py
Normal file
92
tuya-control/devices/lights/windowled.py
Normal file
@ -0,0 +1,92 @@
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bf10d8832c8447c512jedz" # ID de windowled
|
||||
DEVICE_NAME = "windowled"
|
||||
SWITCH_CODE = "switch_led" # Utiliser le code correct pour l'interrupteur
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
# Vérifier si on a bien une réponse
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
# Essayer d'afficher la réponse complète
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
print(f"📊 Type de réponse: {type(status).__name__}")
|
||||
|
||||
if isinstance(status, dict):
|
||||
print(f"📊 Clés disponibles: {list(status.keys())}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Vérifier le format de la réponse
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut de l'interrupteur '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
# Vérifier si response n'est pas None avant d'appeler get()
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
44
tuya-control/devices/others/bureau_dino_toggle.py
Normal file
44
tuya-control/devices/others/bureau_dino_toggle.py
Normal file
@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état du bureau dino (allumé/éteint) sans affecter le saber
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "820180048cce4e2aecc7"
|
||||
DEVICE_NAME = "Bureau Dino"
|
||||
|
||||
# Le commutateur principal est sur le DPS 1
|
||||
SWITCH_ID = "1"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état du bureau dino sans affecter le saber"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Pour ce type d'appareil, le DPS 1 contrôle l'alimentation principale
|
||||
current_state = status.get('dps', {}).get(SWITCH_ID, False)
|
||||
|
||||
# Basculer l'état (inverse de l'état actuel)
|
||||
new_state = not current_state
|
||||
result = device.set_value(SWITCH_ID, new_state)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
41
tuya-control/devices/others/sirene_toggle.py
Normal file
41
tuya-control/devices/others/sirene_toggle.py
Normal file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de la sirène intelligente (activée/désactivée)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf4054de281cb6ada8actg"
|
||||
DEVICE_NAME = "Sirène intelligente"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état de la sirène"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Pour ce type d'appareil, le DPS 127 indique l'état de l'alarme
|
||||
current_state = status.get('dps', {}).get('127', False)
|
||||
|
||||
# Basculer l'état (inverse de l'état actuel)
|
||||
new_state = not current_state
|
||||
result = device.set_value('127', new_state)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
tuya-control/devices/plugs/Ecrangauche.py
Normal file
37
tuya-control/devices/plugs/Ecrangauche.py
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de l'écran gauche (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bfc369d2ca89602058xajc"
|
||||
DEVICE_NAME = "ecran gauche"
|
||||
|
||||
# Le commutateur principal est sur le DPS 1
|
||||
SWITCH_ID = "1"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état de l'écran"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device, SWITCH_ID)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
tuya-control/devices/plugs/bureau_toggle.py
Normal file
37
tuya-control/devices/plugs/bureau_toggle.py
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état du PC (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bfe57aa0e61a9b529bzrff"
|
||||
DEVICE_NAME = "PC"
|
||||
|
||||
# Commutateur principal
|
||||
SWITCH_ID = "1"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état du PC"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device, SWITCH_ID)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
tuya-control/devices/plugs/bureaudino.py
Normal file
37
tuya-control/devices/plugs/bureaudino.py
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état du bureau dino (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "820180048cce4e2aecc7"
|
||||
DEVICE_NAME = "bureau dino"
|
||||
|
||||
# Le commutateur principal est sur le DPS 1
|
||||
SWITCH_ID = "1"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état du bureau"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device, SWITCH_ID)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
37
tuya-control/devices/plugs/imprimante3d.py
Normal file
37
tuya-control/devices/plugs/imprimante3d.py
Normal file
@ -0,0 +1,37 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de l'imprimante 3D (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf9043f5954449c435mcec"
|
||||
DEVICE_NAME = "imprimante 3d"
|
||||
|
||||
# Le commutateur principal est sur le DPS 1
|
||||
SWITCH_ID = "1"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état de l'imprimante"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device, SWITCH_ID)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
34
tuya-control/devices/plugs/prise_cafe_toggle.py
Normal file
34
tuya-control/devices/plugs/prise_cafe_toggle.py
Normal file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de la prise café (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, toggle_device, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf3254180de3bdd7bfnbei"
|
||||
DEVICE_NAME = "prise café"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour basculer l'état de la prise"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Basculer l'état et obtenir le nouvel état
|
||||
new_state = toggle_device(device)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(new_state is not None, DEVICE_NAME, new_state)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
92
tuya-control/devices/plugs/sw2.py
Normal file
92
tuya-control/devices/plugs/sw2.py
Normal file
@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour basculer l'état de SW2 (allumé/éteint)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# Informations de l'appareil
|
||||
DEVICE_ID = "bf06f9007abca55618iiwv" # ID de SW2
|
||||
DEVICE_NAME = "SW2" # Nom de l'appareil
|
||||
SWITCH_CODE = "switch_1" # Code pour l'interrupteur
|
||||
|
||||
def main():
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
# Activer le mode debug dans tinytuya
|
||||
tinytuya.set_debug(True)
|
||||
|
||||
# Lire l'état actuel
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
try:
|
||||
print(f"📊 Réponse brute: {status}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
is_on = None
|
||||
|
||||
# Analyse du statut
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(result, dict) and "status" in result:
|
||||
for item in result["status"]:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
elif isinstance(status, list):
|
||||
for item in status:
|
||||
if isinstance(item, dict) and item.get("code") == SWITCH_CODE:
|
||||
is_on = item.get("value")
|
||||
break
|
||||
|
||||
if is_on is None:
|
||||
print(f"❌ Impossible de trouver le statut '{SWITCH_CODE}' pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
print(f"ℹ️ État actuel de {DEVICE_NAME}: {'ALLUMÉ' if is_on else 'ÉTEINT'}")
|
||||
|
||||
# Basculer l'état
|
||||
new_value = not is_on
|
||||
print(f"ℹ️ Nouvel état à appliquer: {'ALLUMÉ' if new_value else 'ÉTEINT'}")
|
||||
|
||||
# Envoyer la commande
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": new_value}
|
||||
]
|
||||
}
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant {'allumé' if new_value else 'éteint'}")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
tuya-control/devices/shutters/volet_cuisine_toggle.py
Normal file
48
tuya-control/devices/shutters/volet_cuisine_toggle.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour contrôler le volet de la cuisine (ouvrir/fermer/arrêter)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, control_shutter, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf81367b1f5c267af7yyht"
|
||||
DEVICE_NAME = "volet cuisine"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour contrôler le volet"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Si le volet est arrêté, l'ouvrir
|
||||
# Si le volet est en mouvement, l'arrêter
|
||||
current_state = status.get('dps', {}).get('1', 'stop')
|
||||
|
||||
if current_state == "stop":
|
||||
# Si arrêté, on ouvre
|
||||
action = "up" # Utilise "forward" en interne
|
||||
else:
|
||||
# Si en mouvement, on arrête
|
||||
action = "stop"
|
||||
|
||||
# Exécuter l'action et obtenir le résultat
|
||||
result = control_shutter(device, action)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result, DEVICE_NAME, action)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
tuya-control/devices/shutters/volet_delia_toggle.py
Normal file
48
tuya-control/devices/shutters/volet_delia_toggle.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour contrôler le volet Delia (ouvrir/fermer/arrêter)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, control_shutter, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf5b5aa8312d543135xxak"
|
||||
DEVICE_NAME = "volet delia"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour contrôler le volet"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Si le volet est arrêté, l'ouvrir
|
||||
# Si le volet est en mouvement, l'arrêter
|
||||
current_state = status.get('dps', {}).get('1', 'stop')
|
||||
|
||||
if current_state == "stop":
|
||||
# Si arrêté, on ouvre
|
||||
action = "up" # Utilise "forward" en interne
|
||||
else:
|
||||
# Si en mouvement, on arrête
|
||||
action = "stop"
|
||||
|
||||
# Exécuter l'action et obtenir le résultat
|
||||
result = control_shutter(device, action)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result, DEVICE_NAME, action)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
77
tuya-control/devices/shutters/volet_dino_close_toggle.py
Normal file
77
tuya-control/devices/shutters/volet_dino_close_toggle.py
Normal file
@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour fermer le volet Dino
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bff082745aedf9fc1aqy3e" # ID du volet Dino
|
||||
DEVICE_NAME = "Volet dino" # Nom de l'appareil
|
||||
|
||||
# Code des commandes du volet
|
||||
SWITCH_CODE = "control" # Pour les volets Tuya, le code est souvent "control"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour fermer le volet via Cloud"""
|
||||
# Connexion au Cloud
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
tinytuya.set_debug(True) # Pour debug si besoin
|
||||
|
||||
# Lire l'état actuel du volet
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
try:
|
||||
print(f"📊 Réponse brute: {json.dumps(status, indent=2)}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
# Vérification de l'état actuel
|
||||
current_state = None
|
||||
if isinstance(status, dict) and "result" in status:
|
||||
result = status["result"]
|
||||
for item in result:
|
||||
if item.get("code") == SWITCH_CODE:
|
||||
current_state = item.get("value")
|
||||
break
|
||||
|
||||
print(f"ℹ️ État actuel du volet: {current_state}")
|
||||
|
||||
# Envoyer la commande pour fermer le volet
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": "close"}, # Essayez "close" pour fermer
|
||||
# Vous pouvez également essayer "fermer" si cela est supporté
|
||||
]
|
||||
}
|
||||
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant fermé")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
66
tuya-control/devices/shutters/volet_dino_open_toggle.py
Normal file
66
tuya-control/devices/shutters/volet_dino_open_toggle.py
Normal file
@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour ouvrir le volet Dino
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import tinytuya
|
||||
import json
|
||||
|
||||
# Informations Cloud Tuya
|
||||
API_REGION = "eu"
|
||||
API_KEY = "fdjdjurkm34yyjp77c7d"
|
||||
API_SECRET = "3e71807fb0c6406792bdf4f07f98e577"
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bff082745aedf9fc1aqy3e" # ID du volet Dino
|
||||
DEVICE_NAME = "Volet dino" # Nom de l'appareil
|
||||
|
||||
# Code des commandes du volet
|
||||
SWITCH_CODE = "control" # Pour les volets Tuya, le code est souvent "control"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour ouvrir le volet via Cloud"""
|
||||
# Connexion au Cloud
|
||||
cloud = tinytuya.Cloud(
|
||||
apiRegion=API_REGION,
|
||||
apiKey=API_KEY,
|
||||
apiSecret=API_SECRET
|
||||
)
|
||||
|
||||
tinytuya.set_debug(True) # Pour debug si besoin
|
||||
|
||||
# Lire l'état actuel du volet
|
||||
print(f"🔍 Récupération du statut pour l'appareil {DEVICE_ID}...")
|
||||
status = cloud.getstatus(DEVICE_ID)
|
||||
|
||||
if not status:
|
||||
print(f"❌ Aucune réponse de l'API Cloud pour {DEVICE_NAME}")
|
||||
return
|
||||
|
||||
try:
|
||||
print(f"📊 Réponse brute: {json.dumps(status, indent=2)}")
|
||||
except Exception as e:
|
||||
print(f"⚠️ Erreur lors de l'affichage de la réponse: {e}")
|
||||
|
||||
# Envoyer la commande pour ouvrir le volet
|
||||
commands = {
|
||||
"commands": [
|
||||
{"code": SWITCH_CODE, "value": "open"}, # Utiliser "open" pour ouvrir
|
||||
# Vous pouvez également essayer "ouvrir" si cela est supporté
|
||||
]
|
||||
}
|
||||
|
||||
print(f"📤 Envoi de la commande: {json.dumps(commands, indent=2)}")
|
||||
response = cloud.sendcommand(DEVICE_ID, commands)
|
||||
print(f"📥 Réponse reçue: {json.dumps(response, indent=2) if response else 'Aucune réponse'}")
|
||||
|
||||
if response is not None and response.get("success"):
|
||||
print(f"✅ {DEVICE_NAME} est maintenant ouvert")
|
||||
else:
|
||||
error_msg = response.get("msg", "Erreur inconnue") if response else "Pas de réponse"
|
||||
print(f"❌ Échec pour {DEVICE_NAME}: {error_msg}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
tuya-control/devices/shutters/volet_jeanluc_toggle.py
Normal file
48
tuya-control/devices/shutters/volet_jeanluc_toggle.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour contrôler le volet Jean Luc (ouvrir/fermer/arrêter)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, control_shutter, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bf0e197f469e9f2670fb27"
|
||||
DEVICE_NAME = "volet jean luc"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour contrôler le volet"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Si le volet est arrêté, l'ouvrir
|
||||
# Si le volet est en mouvement, l'arrêter
|
||||
current_state = status.get('dps', {}).get('1', 'stop')
|
||||
|
||||
if current_state == "stop":
|
||||
# Si arrêté, on ouvre
|
||||
action = "up" # Utilise "forward" en interne
|
||||
else:
|
||||
# Si en mouvement, on arrête
|
||||
action = "stop"
|
||||
|
||||
# Exécuter l'action et obtenir le résultat
|
||||
result = control_shutter(device, action)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result, DEVICE_NAME, action)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
48
tuya-control/devices/shutters/volet_salon_toggle.py
Normal file
48
tuya-control/devices/shutters/volet_salon_toggle.py
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour contrôler le volet du salon (ouvrir/fermer/arrêter)
|
||||
À utiliser avec StreamDeck
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
|
||||
from common.utils import connect_device, control_shutter, report_for_streamdeck
|
||||
|
||||
# ID et nom de l'appareil
|
||||
DEVICE_ID = "bfc74a089fe0a9a50d2eeg"
|
||||
DEVICE_NAME = "volet salon"
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour contrôler le volet du salon"""
|
||||
# Connexion à l'appareil
|
||||
device = connect_device(DEVICE_ID)
|
||||
if not device:
|
||||
report_for_streamdeck(False, DEVICE_NAME)
|
||||
return
|
||||
|
||||
# Obtenir l'état actuel
|
||||
status = device.status()
|
||||
|
||||
# Si le volet est arrêté, l'ouvrir
|
||||
# Si le volet est en mouvement, l'arrêter
|
||||
current_state = status.get('dps', {}).get('1', 'stop')
|
||||
|
||||
if current_state == "stop":
|
||||
# Si arrêté, on ouvre
|
||||
action = "up" # Utilise "forward" en interne
|
||||
else:
|
||||
# Si en mouvement, on arrête
|
||||
action = "stop"
|
||||
|
||||
# Exécuter l'action et obtenir le résultat
|
||||
result = control_shutter(device, action)
|
||||
|
||||
# Rapport pour StreamDeck
|
||||
report_for_streamdeck(result, DEVICE_NAME, action)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
62
tuya-control/scripts/scan_devices.py
Normal file
62
tuya-control/scripts/scan_devices.py
Normal file
@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour scanner et afficher tous les appareils Tuya disponibles sur le réseau
|
||||
Utile pour diagnostiquer les problèmes de connexion
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
import time
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from common.utils import scan_for_devices
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour scanner et afficher les appareils"""
|
||||
print("Recherche des appareils Tuya sur le réseau...")
|
||||
print("Veuillez patienter, cela peut prendre jusqu'à 30 secondes...")
|
||||
|
||||
# Réaliser un scan du réseau
|
||||
devices = scan_for_devices()
|
||||
|
||||
if not devices:
|
||||
print("Aucun appareil trouvé sur le réseau.")
|
||||
return
|
||||
|
||||
print(f"\nAppareils trouvés: {len(devices)}\n")
|
||||
|
||||
# Afficher les informations détaillées pour chaque appareil
|
||||
for device in devices:
|
||||
print("="*50)
|
||||
print(f"Nom : {device.get('name', 'Inconnu')}")
|
||||
print(f"ID : {device.get('id', 'N/A')}")
|
||||
print(f"IP : {device.get('ip', 'N/A')}")
|
||||
print(f"Produit : {device.get('productKey', 'N/A')}")
|
||||
print(f"Version : {device.get('ver', 'N/A')}")
|
||||
|
||||
# Afficher l'état actuel si disponible
|
||||
if 'dps' in device:
|
||||
print("\nÉtat actuel:")
|
||||
try:
|
||||
# Formater les DPS pour une meilleure lisibilité
|
||||
dps_formatted = json.dumps(device['dps'], indent=2, ensure_ascii=False)
|
||||
print(dps_formatted)
|
||||
except:
|
||||
print(device['dps'])
|
||||
|
||||
print("="*50 + "\n")
|
||||
|
||||
# Sauvegarder les résultats dans un fichier snapshot
|
||||
timestamp = int(time.time())
|
||||
snapshot_file = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), f"snapshot_{timestamp}.json")
|
||||
|
||||
with open(snapshot_file, 'w', encoding='utf-8') as f:
|
||||
json.dump({"timestamp": time.time(), "devices": devices}, f, indent=4, ensure_ascii=False)
|
||||
|
||||
print(f"Résultats sauvegardés dans {snapshot_file}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
72
tuya-control/scripts/status_devices.py
Normal file
72
tuya-control/scripts/status_devices.py
Normal file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Script pour afficher le statut de tous les appareils Tuya connus
|
||||
Utile pour avoir une vue d'ensemble rapide
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import json
|
||||
|
||||
# Ajouter le répertoire parent au path pour les imports
|
||||
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
from common.utils import connect_device, get_device_status_text
|
||||
|
||||
def main():
|
||||
"""Fonction principale pour afficher le statut des appareils"""
|
||||
print("Récupération du statut des appareils Tuya...\n")
|
||||
|
||||
# Charger la liste des appareils depuis devices.json
|
||||
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
devices_file = os.path.join(base_dir, 'devices.json')
|
||||
|
||||
try:
|
||||
with open(devices_file, 'r', encoding='utf-8') as f:
|
||||
devices = json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Erreur lors du chargement du fichier devices.json: {e}")
|
||||
return
|
||||
|
||||
# Catégoriser les appareils
|
||||
categories = {
|
||||
"lights": [], # Lumières
|
||||
"shutters": [], # Volets
|
||||
"plugs": [], # Prises
|
||||
"cameras": [], # Caméras
|
||||
"others": [] # Autres appareils
|
||||
}
|
||||
|
||||
# Trier les appareils par catégorie
|
||||
for device in devices:
|
||||
device_id = device.get('id')
|
||||
device_name = device.get('name', 'Appareil inconnu')
|
||||
product_key = device.get('product_id', '')
|
||||
|
||||
# Classifier selon le type
|
||||
if product_key in ['key8u54q9dtru5jw', 'keynremrcjf97twe']:
|
||||
categories["lights"].append((device_id, device_name))
|
||||
elif product_key in ['4pqpkp1rskkjtxay']:
|
||||
categories["shutters"].append((device_id, device_name))
|
||||
elif product_key in ['uqehhcrmk5depvtl']:
|
||||
categories["plugs"].append((device_id, device_name))
|
||||
elif product_key in ['biw8urjw2dvss3ur', 'pg7xibyidyvt5pia']:
|
||||
categories["cameras"].append((device_id, device_name))
|
||||
else:
|
||||
categories["others"].append((device_id, device_name))
|
||||
|
||||
# Afficher le statut par catégorie
|
||||
for category, cat_devices in categories.items():
|
||||
if not cat_devices:
|
||||
continue
|
||||
|
||||
print(f"\n=== {category.upper()} ===")
|
||||
|
||||
for device_id, device_name in cat_devices:
|
||||
status_text = get_device_status_text(device_id)
|
||||
print(f" - {status_text}")
|
||||
|
||||
print("\nTerminé!")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5727
tuya-raw.json
Normal file
5727
tuya-raw.json
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user