capyy 0.5.1__tar.gz → 0.5.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {capyy-0.5.1 → capyy-0.5.2}/PKG-INFO +7 -7
- {capyy-0.5.1 → capyy-0.5.2}/README.md +6 -6
- {capyy-0.5.1 → capyy-0.5.2}/capy/__main__.py +34 -16
- {capyy-0.5.1 → capyy-0.5.2}/capy/_project.py +4 -4
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/__init__.py +2 -2
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/__main__.py +23 -23
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_homeassistant.py +1 -1
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_hue.py +2 -2
- {capyy-0.5.1 → capyy-0.5.2}/capy/network.py +10 -6
- {capyy-0.5.1 → capyy-0.5.2}/capyy.egg-info/PKG-INFO +7 -7
- {capyy-0.5.1 → capyy-0.5.2}/capyy.egg-info/entry_points.txt +1 -0
- {capyy-0.5.1 → capyy-0.5.2}/pyproject.toml +3 -2
- {capyy-0.5.1 → capyy-0.5.2}/LICENSE +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/__init__.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/_tls.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_base.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_net.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_shelly.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_wiz.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/domo/_yeelight.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capy/wifi.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capyy.egg-info/SOURCES.txt +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capyy.egg-info/dependency_links.txt +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/capyy.egg-info/top_level.txt +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/setup.cfg +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/tests/test_capy.py +0 -0
- {capyy-0.5.1 → capyy-0.5.2}/tests/test_domo.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capyy
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Easy, encrypted networking for Python: programs that talk (local, Wi-Fi, internet), home automation, and projects run with cy
|
|
5
5
|
Author: Izac
|
|
6
6
|
License-Expression: MIT
|
|
@@ -82,7 +82,7 @@ what could not be converted.
|
|
|
82
82
|
Describe the whole project once, then never repeat ports or hosts:
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
|
|
85
|
+
capy new my-game # folder + capy.config.json + server.py + client.py
|
|
86
86
|
cd my-game
|
|
87
87
|
cy run # starts the server, runs the client, stops the server
|
|
88
88
|
```
|
|
@@ -99,7 +99,7 @@ app.call("hello", nom="Izac") # client side
|
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
`mode` can be `local`, `wifi` or `network` (with `relay`, `key`, `fingerprint`). Strings starting with `$` are read
|
|
102
|
-
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `
|
|
102
|
+
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `capy new`.
|
|
103
103
|
|
|
104
104
|
## Encryption (TLS)
|
|
105
105
|
|
|
@@ -131,7 +131,7 @@ A machine behind a home router cannot be reached from the internet, so `capy.net
|
|
|
131
131
|
clients call that name. Everything is encrypted, and the connection is kept open between calls.
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
|
-
|
|
134
|
+
capy relay 3879 my-secret-key # on the VPS (open the port in its firewall)
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
```python
|
|
@@ -158,9 +158,9 @@ capy.domo.serve(home) # control it remotely through capy / capy.wifi /
|
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
capy domo scan
|
|
162
|
+
capy domo pair hue
|
|
163
|
+
capy domo salon on 30% orange
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
## License
|
|
@@ -60,7 +60,7 @@ what could not be converted.
|
|
|
60
60
|
Describe the whole project once, then never repeat ports or hosts:
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
|
-
|
|
63
|
+
capy new my-game # folder + capy.config.json + server.py + client.py
|
|
64
64
|
cd my-game
|
|
65
65
|
cy run # starts the server, runs the client, stops the server
|
|
66
66
|
```
|
|
@@ -77,7 +77,7 @@ app.call("hello", nom="Izac") # client side
|
|
|
77
77
|
```
|
|
78
78
|
|
|
79
79
|
`mode` can be `local`, `wifi` or `network` (with `relay`, `key`, `fingerprint`). Strings starting with `$` are read
|
|
80
|
-
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `
|
|
80
|
+
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `capy new`.
|
|
81
81
|
|
|
82
82
|
## Encryption (TLS)
|
|
83
83
|
|
|
@@ -109,7 +109,7 @@ A machine behind a home router cannot be reached from the internet, so `capy.net
|
|
|
109
109
|
clients call that name. Everything is encrypted, and the connection is kept open between calls.
|
|
110
110
|
|
|
111
111
|
```bash
|
|
112
|
-
|
|
112
|
+
capy relay 3879 my-secret-key # on the VPS (open the port in its firewall)
|
|
113
113
|
```
|
|
114
114
|
|
|
115
115
|
```python
|
|
@@ -136,9 +136,9 @@ capy.domo.serve(home) # control it remotely through capy / capy.wifi /
|
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
```bash
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
139
|
+
capy domo scan
|
|
140
|
+
capy domo pair hue
|
|
141
|
+
capy domo salon on 30% orange
|
|
142
142
|
```
|
|
143
143
|
|
|
144
144
|
## License
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Deux commandes, installées avec capy :
|
|
2
2
|
#
|
|
3
|
-
# cy :
|
|
3
|
+
# cy : DANS un projet capy (un dossier avec capy.config.json, ou en dessous)
|
|
4
4
|
# cy -> montre le projet (nom, mode, adresse, fichiers, scripts…)
|
|
5
5
|
# cy NOM [args…] -> lance le script NOM de "scripts" (comme npm run)
|
|
6
6
|
# cy scripts -> liste les scripts
|
|
7
7
|
# cy server / cy client -> lance un fichier de "files"
|
|
8
8
|
# cy run -> lance le serveur en fond, puis le client, puis arrête le serveur
|
|
9
9
|
#
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
10
|
+
# capy : tout le reste (et tout ce que fait cy)
|
|
11
|
+
# capy new NOM [mode] -> crée un dossier NOM avec capy.config.json, server.py, client.py
|
|
12
|
+
# capy init [nom] [mode] -> crée juste capy.config.json ici
|
|
13
|
+
# capy domo … -> la domotique (capy domo help)
|
|
14
|
+
# capy relay PORT [CLÉ] -> lance un relais capy.network (sur le VPS)
|
|
13
15
|
# mode : local (par défaut), wifi ou network
|
|
16
|
+
# python3 -m capy = capy (si la commande n'est pas dans le PATH)
|
|
14
17
|
|
|
15
18
|
import difflib
|
|
16
19
|
import socket
|
|
@@ -27,9 +30,11 @@ USAGE = f"""Dans un projet capy ({FILE_NAME}) :
|
|
|
27
30
|
cy scripts liste les scripts
|
|
28
31
|
cy server / client lance un fichier de "files"
|
|
29
32
|
cy run serveur en fond + client, puis arrête le serveur
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
Partout :
|
|
34
|
+
capy new NOM [mode] crée un projet complet (config, server.py, client.py)
|
|
35
|
+
capy init [nom] [mode] crée juste {FILE_NAME} ici
|
|
36
|
+
capy domo … la domotique (capy domo help)
|
|
37
|
+
capy relay PORT [CLÉ] lance un relais capy.network
|
|
33
38
|
modes : {", ".join(MODES)}"""
|
|
34
39
|
|
|
35
40
|
|
|
@@ -37,9 +42,9 @@ Créer un projet :
|
|
|
37
42
|
def _project():
|
|
38
43
|
path = find(".")
|
|
39
44
|
if path is None:
|
|
40
|
-
sys.exit(f"
|
|
41
|
-
f" Crée un projet :
|
|
42
|
-
f" ou juste le fichier :
|
|
45
|
+
sys.exit(f"Pas de {FILE_NAME} ici ni au-dessus : ce dossier n'est pas un projet capy.\n"
|
|
46
|
+
f" Crée un projet : capy new mon-projet\n"
|
|
47
|
+
f" ou juste le fichier : capy init")
|
|
43
48
|
try:
|
|
44
49
|
return project(path)
|
|
45
50
|
except ValueError as e:
|
|
@@ -111,12 +116,20 @@ def main(args):
|
|
|
111
116
|
if command in ("-h", "--help", "help"):
|
|
112
117
|
print(USAGE)
|
|
113
118
|
return
|
|
119
|
+
if command == "domo": # capy domo salon on
|
|
120
|
+
from .domo.__main__ import cli as domo_cli
|
|
121
|
+
domo_cli(args[1:])
|
|
122
|
+
return
|
|
123
|
+
if command in ("relay", "network"): # capy relay 3879 CLÉ
|
|
124
|
+
from .network import cli as relay_cli
|
|
125
|
+
relay_cli(args[1:])
|
|
126
|
+
return
|
|
114
127
|
if command in ("init", "new"):
|
|
115
128
|
rest = args[1:]
|
|
116
129
|
mode = next((a for a in rest if a in MODES), "local")
|
|
117
130
|
name = next((a for a in rest if a not in MODES), None)
|
|
118
131
|
if command == "new" and not name:
|
|
119
|
-
sys.exit("Usage :
|
|
132
|
+
sys.exit("Usage : capy new NOM [mode]")
|
|
120
133
|
try:
|
|
121
134
|
path = new(name, mode) / FILE_NAME if command == "new" else init(name=name, mode=mode)
|
|
122
135
|
except (FileExistsError, ValueError) as e:
|
|
@@ -157,13 +170,18 @@ def main(args):
|
|
|
157
170
|
sys.exit(f"capy : commande, script ou fichier {command!r} inconnu (possibles : {', '.join(names)})\n\n{USAGE}")
|
|
158
171
|
|
|
159
172
|
|
|
160
|
-
# La commande cy : seulement les commandes d'un projet
|
|
173
|
+
# La commande cy : seulement les commandes d'un projet
|
|
161
174
|
def cli():
|
|
162
175
|
args = sys.argv[1:]
|
|
163
|
-
if args[:1] in (["new"], ["init"]):
|
|
164
|
-
sys.exit(f"cy sert dans un projet
|
|
176
|
+
if args[:1] in (["new"], ["init"], ["domo"], ["relay"], ["network"]):
|
|
177
|
+
sys.exit(f"cy sert dans un projet capy ; pour ça, c'est la commande capy : capy {' '.join(args)}")
|
|
165
178
|
main(args)
|
|
166
179
|
|
|
167
180
|
|
|
168
|
-
|
|
181
|
+
# La commande capy (et python3 -m capy) : tout
|
|
182
|
+
def capy_cli():
|
|
169
183
|
main(sys.argv[1:])
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
if __name__ == "__main__":
|
|
187
|
+
capy_cli()
|
|
@@ -46,7 +46,7 @@ FIELDS = {
|
|
|
46
46
|
|
|
47
47
|
EXAMPLE = {"name": "mon-projet", "mode": "local", "host": "localhost", "port": 4000, "tls": True,
|
|
48
48
|
"files": {"server": "server.py", "client": "client.py"}}
|
|
49
|
-
COMMANDS = ("init", "new", "run", "scripts", "help") # Mots réservés de cy /
|
|
49
|
+
COMMANDS = ("init", "new", "run", "scripts", "help", "domo", "relay") # Mots réservés de cy / capy (pas des noms de fichiers ni de scripts)
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
# Dossier du script lancé (comme simplesuit.json) ; sans script (python3 -c, REPL) -> dossier actuel
|
|
@@ -274,7 +274,7 @@ def project(path=None) -> Project:
|
|
|
274
274
|
if found is None:
|
|
275
275
|
raise FileNotFoundError(
|
|
276
276
|
f"capy.project : aucun {FILE_NAME} trouvé dans {_main_dir()} ni au-dessus.\n"
|
|
277
|
-
f" Crée-le avec :
|
|
277
|
+
f" Crée-le avec : capy init\n"
|
|
278
278
|
f" ou écris-le toi-même, par exemple : {jsonlib.dumps(EXAMPLE, ensure_ascii=False)}"
|
|
279
279
|
)
|
|
280
280
|
return Project(found)
|
|
@@ -284,7 +284,7 @@ def project(path=None) -> Project:
|
|
|
284
284
|
return Project(path / FILE_NAME if path.is_dir() else path)
|
|
285
285
|
|
|
286
286
|
|
|
287
|
-
# Écrire un capy.config.json de départ (
|
|
287
|
+
# Écrire un capy.config.json de départ (capy init [nom] [mode])
|
|
288
288
|
def init(folder=None, name=None, mode="local"):
|
|
289
289
|
if mode not in MODES:
|
|
290
290
|
raise ValueError(f"capy init : mode {mode!r} inconnu, choisis parmi : {', '.join(MODES)}")
|
|
@@ -331,7 +331,7 @@ print(capy.get(reponse, "message"))
|
|
|
331
331
|
'''
|
|
332
332
|
|
|
333
333
|
|
|
334
|
-
# Créer un projet complet : dossier + capy.config.json + server.py + client.py (
|
|
334
|
+
# Créer un projet complet : dossier + capy.config.json + server.py + client.py (capy new nom)
|
|
335
335
|
def new(name, mode="local", parent=None):
|
|
336
336
|
folder = pth.Path(parent or pth.Path.cwd()) / name
|
|
337
337
|
if folder.exists() and any(folder.iterdir()):
|
|
@@ -253,14 +253,14 @@ class Home:
|
|
|
253
253
|
if host in self.hue:
|
|
254
254
|
lights += _hue.lights(host, _env(self.hue[host]))
|
|
255
255
|
else:
|
|
256
|
-
self.hints.append(f"Pont Hue trouvé à {host} : appaire-le avec
|
|
256
|
+
self.hints.append(f"Pont Hue trouvé à {host} : appaire-le avec capy domo pair hue {host}")
|
|
257
257
|
return lights
|
|
258
258
|
|
|
259
259
|
def _scan_homeassistant(self, timeout, addresses):
|
|
260
260
|
if self.homeassistant:
|
|
261
261
|
return _homeassistant.entities(_env(self.homeassistant["url"]), _env(self.homeassistant["token"]))
|
|
262
262
|
for url in _homeassistant.servers(timeout, addresses.get("homeassistant")):
|
|
263
|
-
self.hints.append(f"Home Assistant trouvé à {url} :
|
|
263
|
+
self.hints.append(f"Home Assistant trouvé à {url} : capy domo pair homeassistant {url}")
|
|
264
264
|
return []
|
|
265
265
|
|
|
266
266
|
# --- Appairage --------------------------------------------
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
#
|
|
1
|
+
# capy domo : piloter la maison depuis le terminal
|
|
2
2
|
#
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
3
|
+
# capy domo scan chercher les appareils du réseau (et les ajouter)
|
|
4
|
+
# capy domo pair hue [IP] appairer un pont Hue (appuyer sur son bouton)
|
|
5
|
+
# capy domo pair homeassistant URL brancher Home Assistant (jeton demandé)
|
|
6
|
+
# capy domo list les appareils, groupes et scènes, avec leur état
|
|
7
|
+
# capy domo salon on 30% orange allumer, luminosité, couleur (ou off, toggle, 2700K, chaud…)
|
|
8
|
+
# capy domo scene film lancer une scène
|
|
9
|
+
# capy domo serve rendre la maison pilotable à distance
|
|
10
|
+
# capy domo --remote salon off piloter une maison à distance (capy.config.json)
|
|
11
11
|
|
|
12
12
|
import getpass
|
|
13
13
|
import os
|
|
@@ -20,14 +20,14 @@ import capy
|
|
|
20
20
|
from . import FILE_NAME, WHITES, Home, Remote, _hue, find, serve, to_kelvin, to_rgb
|
|
21
21
|
|
|
22
22
|
USAGE = """Usage :
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
capy domo scan chercher les appareils du réseau
|
|
24
|
+
capy domo pair hue [IP] appairer un pont Hue
|
|
25
|
+
capy domo pair homeassistant URL brancher Home Assistant
|
|
26
|
+
capy domo list appareils, groupes, scènes et état
|
|
27
|
+
capy domo NOM on|off|toggle|50%|orange|#FF7800|2700K|chaud …
|
|
28
|
+
capy domo scene NOM lancer une scène
|
|
29
|
+
capy domo serve pilotable à distance
|
|
30
|
+
capy domo --remote NOM … piloter une maison à distance"""
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
# "on 30% orange" -> {"on": True, "brightness": 30, "color": "orange"} (ou "toggle")
|
|
@@ -97,7 +97,7 @@ def main(args):
|
|
|
97
97
|
if brand == "hue":
|
|
98
98
|
hosts = rest[1:] or _hue.bridges()
|
|
99
99
|
if not hosts:
|
|
100
|
-
sys.exit("Aucun pont Hue trouvé : donne son IP, ex :
|
|
100
|
+
sys.exit("Aucun pont Hue trouvé : donne son IP, ex : capy domo pair hue 192.168.1.10")
|
|
101
101
|
host = hosts[0]
|
|
102
102
|
input(f"Appuie sur le gros bouton rond du pont Hue ({host}), puis sur Entrée… ")
|
|
103
103
|
for _ in range(30):
|
|
@@ -110,7 +110,7 @@ def main(args):
|
|
|
110
110
|
sys.exit("Le pont n'a pas vu le bouton : réessaie (tu as 30 s après l'appui)")
|
|
111
111
|
elif brand == "homeassistant":
|
|
112
112
|
if len(rest) < 2:
|
|
113
|
-
sys.exit("Donne l'adresse :
|
|
113
|
+
sys.exit("Donne l'adresse : capy domo pair homeassistant http://homeassistant.local:8123")
|
|
114
114
|
if os.environ.get("HA_TOKEN"):
|
|
115
115
|
token = "$HA_TOKEN"
|
|
116
116
|
print("Jeton lu dans la variable HA_TOKEN")
|
|
@@ -118,7 +118,7 @@ def main(args):
|
|
|
118
118
|
token = getpass.getpass("Jeton longue durée (Profil -> Sécurité dans Home Assistant) : ")
|
|
119
119
|
added = home.pair_homeassistant(rest[1], token)
|
|
120
120
|
else:
|
|
121
|
-
sys.exit("Usage :
|
|
121
|
+
sys.exit("Usage : capy domo pair hue [IP] ou pair homeassistant URL")
|
|
122
122
|
for device in added:
|
|
123
123
|
print(f" + {device.name:<18} {device.brand}")
|
|
124
124
|
print(f"{len(added)} appareil(s) ajouté(s) dans {home.save()}")
|
|
@@ -131,7 +131,7 @@ def main(args):
|
|
|
131
131
|
else:
|
|
132
132
|
names, groups, scenes = list(home.devices), home.groups, list(home.scenes)
|
|
133
133
|
states = home.all().state() if home.devices else {}
|
|
134
|
-
print("Appareils :" if names else "Aucun appareil : lance
|
|
134
|
+
print("Appareils :" if names else "Aucun appareil : lance capy domo scan")
|
|
135
135
|
for name in names:
|
|
136
136
|
print(show_state(name, states.get(name, {"reachable": False})))
|
|
137
137
|
if groups:
|
|
@@ -143,7 +143,7 @@ def main(args):
|
|
|
143
143
|
|
|
144
144
|
elif command == "scene":
|
|
145
145
|
if not rest:
|
|
146
|
-
sys.exit("Usage :
|
|
146
|
+
sys.exit("Usage : capy domo scene NOM")
|
|
147
147
|
home.scene(rest[0])
|
|
148
148
|
print(f"Scène {rest[0]!r} lancée")
|
|
149
149
|
|
|
@@ -170,7 +170,7 @@ def main(args):
|
|
|
170
170
|
print(f"{command} : ok")
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
# Point d'entrée de
|
|
173
|
+
# Point d'entrée de capy domo
|
|
174
174
|
def cli(args=None):
|
|
175
175
|
try:
|
|
176
176
|
main(sys.argv[1:] if args is None else args)
|
|
@@ -32,7 +32,7 @@ class HassEntity(Device):
|
|
|
32
32
|
|
|
33
33
|
def _request(self, method, path, body=None):
|
|
34
34
|
if not self.url or not self.token:
|
|
35
|
-
raise ConnectionError("Home Assistant pas configuré :
|
|
35
|
+
raise ConnectionError("Home Assistant pas configuré : capy domo pair homeassistant URL")
|
|
36
36
|
return request(self.url, self.token, method, path, body)
|
|
37
37
|
|
|
38
38
|
def _apply(self, changes):
|
|
@@ -31,7 +31,7 @@ def _check(answer):
|
|
|
31
31
|
return answer
|
|
32
32
|
error = errors[0]
|
|
33
33
|
if error.get("type") == 1:
|
|
34
|
-
raise ConnectionError("le pont Hue ne te connaît pas : refais
|
|
34
|
+
raise ConnectionError("le pont Hue ne te connaît pas : refais capy domo pair hue")
|
|
35
35
|
raise ConnectionError(f"pont Hue : {error.get('description', error)}")
|
|
36
36
|
|
|
37
37
|
|
|
@@ -78,7 +78,7 @@ class HueLight(Device):
|
|
|
78
78
|
|
|
79
79
|
def _path(self, end=""):
|
|
80
80
|
if not self.user:
|
|
81
|
-
raise ConnectionError(f"pas d'appairage avec le pont {self.host} :
|
|
81
|
+
raise ConnectionError(f"pas d'appairage avec le pont {self.host} : capy domo pair hue {self.host}")
|
|
82
82
|
return f"/api/{self.user}/lights/{self.id}{end}"
|
|
83
83
|
|
|
84
84
|
def _apply(self, changes):
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Les serveurs s'y connectent (même derrière une box) et s'enregistrent sous un nom,
|
|
4
4
|
# les clients appellent un nom : le relais fait passer la demande et la réponse.
|
|
5
5
|
#
|
|
6
|
-
# Sur le VPS :
|
|
6
|
+
# Sur le VPS : capy relay 3879 motdepasse
|
|
7
7
|
# Partout ailleurs :
|
|
8
8
|
# capy.network.use("mon-vps.fr:3879", key="motdepasse")
|
|
9
9
|
# capy.network.Server("maison").run() / capy.network.call("maison", "test")
|
|
@@ -495,9 +495,13 @@ def call(name, action, /, **params) -> Any:
|
|
|
495
495
|
return reply["response"]
|
|
496
496
|
|
|
497
497
|
|
|
498
|
-
# Lancer un relais depuis le terminal :
|
|
498
|
+
# Lancer un relais depuis le terminal : capy relay 3879 motdepasse (ou capy relay 3879 motdepasse)
|
|
499
|
+
def cli(args=None):
|
|
500
|
+
args = sys.argv[1:] if args is None else args
|
|
501
|
+
if not args or not args[0].isdigit():
|
|
502
|
+
sys.exit("Usage : capy relay PORT [CLÉ] (ex : capy relay 3879 \"$CAPY_KEY\")")
|
|
503
|
+
Relay(int(args[0]), key=args[1] if len(args) > 1 else None).run()
|
|
504
|
+
|
|
505
|
+
|
|
499
506
|
if __name__ == "__main__":
|
|
500
|
-
|
|
501
|
-
print("Usage : python3 -m capy.network PORT [CLÉ]")
|
|
502
|
-
sys.exit(1)
|
|
503
|
-
Relay(int(sys.argv[1]), key=sys.argv[2] if len(sys.argv) > 2 else None).run()
|
|
507
|
+
cli()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: capyy
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
Summary: Easy, encrypted networking for Python: programs that talk (local, Wi-Fi, internet), home automation, and projects run with cy
|
|
5
5
|
Author: Izac
|
|
6
6
|
License-Expression: MIT
|
|
@@ -82,7 +82,7 @@ what could not be converted.
|
|
|
82
82
|
Describe the whole project once, then never repeat ports or hosts:
|
|
83
83
|
|
|
84
84
|
```bash
|
|
85
|
-
|
|
85
|
+
capy new my-game # folder + capy.config.json + server.py + client.py
|
|
86
86
|
cd my-game
|
|
87
87
|
cy run # starts the server, runs the client, stops the server
|
|
88
88
|
```
|
|
@@ -99,7 +99,7 @@ app.call("hello", nom="Izac") # client side
|
|
|
99
99
|
```
|
|
100
100
|
|
|
101
101
|
`mode` can be `local`, `wifi` or `network` (with `relay`, `key`, `fingerprint`). Strings starting with `$` are read
|
|
102
|
-
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `
|
|
102
|
+
from environment variables, e.g. `"key": "$CAPY_KEY"`. Inside a project, the `cy` command runs its `scripts` like `npm run` (`cy test`, `cy start`) and its files (`cy server`); create a project with `capy new`.
|
|
103
103
|
|
|
104
104
|
## Encryption (TLS)
|
|
105
105
|
|
|
@@ -131,7 +131,7 @@ A machine behind a home router cannot be reached from the internet, so `capy.net
|
|
|
131
131
|
clients call that name. Everything is encrypted, and the connection is kept open between calls.
|
|
132
132
|
|
|
133
133
|
```bash
|
|
134
|
-
|
|
134
|
+
capy relay 3879 my-secret-key # on the VPS (open the port in its firewall)
|
|
135
135
|
```
|
|
136
136
|
|
|
137
137
|
```python
|
|
@@ -158,9 +158,9 @@ capy.domo.serve(home) # control it remotely through capy / capy.wifi /
|
|
|
158
158
|
```
|
|
159
159
|
|
|
160
160
|
```bash
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
capy domo scan
|
|
162
|
+
capy domo pair hue
|
|
163
|
+
capy domo salon on 30% orange
|
|
164
164
|
```
|
|
165
165
|
|
|
166
166
|
## License
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "capyy"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.2"
|
|
8
8
|
description = "Easy, encrypted networking for Python: programs that talk (local, Wi-Fi, internet), home automation, and projects run with cy"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -25,7 +25,8 @@ classifiers = [
|
|
|
25
25
|
]
|
|
26
26
|
|
|
27
27
|
[project.scripts]
|
|
28
|
-
cy = "capy.__main__:cli"
|
|
28
|
+
cy = "capy.__main__:cli" # Dans un projet : cy start, cy test…
|
|
29
|
+
capy = "capy.__main__:capy_cli" # Partout : capy new, capy domo, capy relay… (= python3 -m capy)
|
|
29
30
|
|
|
30
31
|
[project.urls]
|
|
31
32
|
Homepage = "https://libs.zazac.link/capy/"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|