indipyclient 0.0.1__py3-none-any.whl
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.
- indipyclient/__init__.py +5 -0
- indipyclient/__main__.py +101 -0
- indipyclient/console/__init__.py +0 -0
- indipyclient/console/consoleclient.py +438 -0
- indipyclient/console/widgets.py +1353 -0
- indipyclient/console/windows.py +3686 -0
- indipyclient/error.py +10 -0
- indipyclient/events.py +630 -0
- indipyclient/ipyclient.py +771 -0
- indipyclient/propertymembers.py +386 -0
- indipyclient/propertyvectors.py +682 -0
- indipyclient-0.0.1.dist-info/LICENSE +21 -0
- indipyclient-0.0.1.dist-info/METADATA +66 -0
- indipyclient-0.0.1.dist-info/RECORD +16 -0
- indipyclient-0.0.1.dist-info/WHEEL +4 -0
- indipyclient-0.0.1.dist-info/entry_points.txt +3 -0
indipyclient/__init__.py
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from .ipyclient import IPyClient
|
|
2
|
+
from .events import (delProperty, defSwitchVector, defTextVector, defNumberVector, defLightVector, defBLOBVector,
|
|
3
|
+
setSwitchVector, setTextVector, setNumberVector, setLightVector, setBLOBVector, Message, VectorTimeOut)
|
|
4
|
+
|
|
5
|
+
version = "0.0.1"
|
indipyclient/__main__.py
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
|
|
2
|
+
"""Usage is
|
|
3
|
+
|
|
4
|
+
python3 -m indipyclient
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import os, sys, argparse, asyncio, collections, contextlib, pathlib
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
from . import version
|
|
13
|
+
|
|
14
|
+
from .console.consoleclient import ConsoleClient, ConsoleControl
|
|
15
|
+
|
|
16
|
+
from .console.widgets import ERRORDATA
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
async def runclient(client, control):
|
|
20
|
+
try:
|
|
21
|
+
t1 = asyncio.create_task(client.asyncrun())
|
|
22
|
+
t2 = asyncio.create_task(control.asyncrun())
|
|
23
|
+
await asyncio.gather(t1, t2)
|
|
24
|
+
except Exception:
|
|
25
|
+
t1.cancel()
|
|
26
|
+
t2.cancel()
|
|
27
|
+
# wait for tasks to be done
|
|
28
|
+
while (not t1.done()) and (not t2.done()):
|
|
29
|
+
await asyncio.sleep(0)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def main():
|
|
33
|
+
"""The main routine."""
|
|
34
|
+
|
|
35
|
+
parser = argparse.ArgumentParser(usage="python3 -m indipyclient [options]",
|
|
36
|
+
description="INDI terminal client communicating to indi service.",
|
|
37
|
+
epilog="""The BLOB's folder can also be set from within the session.
|
|
38
|
+
Setting loglevel and logfile should only be used for brief
|
|
39
|
+
diagnostic purposes, the logfile could grow very big.
|
|
40
|
+
loglevel:1 log vector tags without members or contents,
|
|
41
|
+
loglevel:2 log vectors and members - but not BLOB contents,
|
|
42
|
+
loglevel:3 log vectors and all contents
|
|
43
|
+
""")
|
|
44
|
+
parser.add_argument("-p", "--port", type=int, default=7624, help="Port of the indi server (default 7624).")
|
|
45
|
+
parser.add_argument("--host", default="localhost", help="Hostname/IP of the indi server (default localhost).")
|
|
46
|
+
parser.add_argument("-b", "--blobs", help="Optional folder where BLOB's will be saved.")
|
|
47
|
+
parser.add_argument("--loglevel", help="Enables logging, value 1, 2 or 3.")
|
|
48
|
+
parser.add_argument("--logfile", help="File where logs will be saved")
|
|
49
|
+
|
|
50
|
+
parser.add_argument("--version", action="version", version=version)
|
|
51
|
+
args = parser.parse_args()
|
|
52
|
+
|
|
53
|
+
eventque = collections.deque(maxlen=4)
|
|
54
|
+
|
|
55
|
+
if args.blobs:
|
|
56
|
+
try:
|
|
57
|
+
blobfolder = pathlib.Path(args.blobs).expanduser().resolve()
|
|
58
|
+
except Exception:
|
|
59
|
+
print("Error: If given, the BLOB's folder should be an existing directory")
|
|
60
|
+
return 1
|
|
61
|
+
else:
|
|
62
|
+
if not blobfolder.is_dir():
|
|
63
|
+
print("Error: If given, the BLOB's folder should be an existing directory")
|
|
64
|
+
return 1
|
|
65
|
+
else:
|
|
66
|
+
blobfolder = None
|
|
67
|
+
|
|
68
|
+
# On receiving an event, the client appends it into eventque
|
|
69
|
+
client = ConsoleClient(indihost=args.host, indiport=args.port, eventque=eventque)
|
|
70
|
+
|
|
71
|
+
if args.loglevel and args.logfile:
|
|
72
|
+
try:
|
|
73
|
+
loglevel = int(args.loglevel)
|
|
74
|
+
if loglevel not in (1,2,3):
|
|
75
|
+
print("Error: If given, the loglevel should be 1, 2 or 3")
|
|
76
|
+
return 1
|
|
77
|
+
except:
|
|
78
|
+
print("Error: If given, the loglevel should be 1, 2 or 3")
|
|
79
|
+
return 1
|
|
80
|
+
client.setlogging(loglevel, args.logfile)
|
|
81
|
+
|
|
82
|
+
# Monitors eventque and acts on the events, creates the console screens
|
|
83
|
+
control = ConsoleControl(client, blobfolder=blobfolder)
|
|
84
|
+
|
|
85
|
+
asyncio.run(runclient(client, control))
|
|
86
|
+
|
|
87
|
+
# ERRORDATA is a list of any traceback.TracebackException() objects
|
|
88
|
+
# which records exceptions which may have occurred. They are printed
|
|
89
|
+
# here, after the console has closed down to avoid messing up
|
|
90
|
+
# the console formatting
|
|
91
|
+
|
|
92
|
+
if ERRORDATA:
|
|
93
|
+
for errortrace in ERRORDATA:
|
|
94
|
+
print("".join(errortrace.format()))
|
|
95
|
+
print("------------------")
|
|
96
|
+
|
|
97
|
+
return 0
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if __name__ == "__main__":
|
|
101
|
+
sys.exit(main())
|
|
File without changes
|
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
|
|
2
|
+
import asyncio, sys
|
|
3
|
+
|
|
4
|
+
import curses
|
|
5
|
+
|
|
6
|
+
from traceback import TracebackException as TBE
|
|
7
|
+
|
|
8
|
+
from ..ipyclient import IPyClient
|
|
9
|
+
from ..events import (delProperty, defSwitchVector, defTextVector, defNumberVector, defLightVector, defBLOBVector,
|
|
10
|
+
setSwitchVector, setTextVector, setNumberVector, setLightVector, setBLOBVector, Message, VectorTimeOut)
|
|
11
|
+
|
|
12
|
+
from . import windows
|
|
13
|
+
from . import widgets
|
|
14
|
+
|
|
15
|
+
# set limit to terminal size
|
|
16
|
+
MINROWS = 22
|
|
17
|
+
MINCOLS = 78
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ConsoleClient(IPyClient):
|
|
21
|
+
|
|
22
|
+
"""Overrides IPyClient
|
|
23
|
+
On receiving an event, appends it into eventque
|
|
24
|
+
Which will pass the received event into ConsoleControl"""
|
|
25
|
+
|
|
26
|
+
async def rxevent(self, event):
|
|
27
|
+
"""Add event to eventque"""
|
|
28
|
+
self.clientdata['eventque'].appendleft(event)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ConsoleControl:
|
|
32
|
+
|
|
33
|
+
def __init__(self, client, blobfolder=None):
|
|
34
|
+
"""client is an instance of ConsoleClient
|
|
35
|
+
If given, blobfolder will be the folder where BLOBs will be saved"""
|
|
36
|
+
self.client = client
|
|
37
|
+
self.blobfolder = blobfolder
|
|
38
|
+
if self.blobfolder:
|
|
39
|
+
self.blobenabled = True
|
|
40
|
+
else:
|
|
41
|
+
self.blobenabled = False
|
|
42
|
+
|
|
43
|
+
# this is populated with events as they are received
|
|
44
|
+
self.eventque = self.client.clientdata['eventque']
|
|
45
|
+
|
|
46
|
+
# set up screen
|
|
47
|
+
self.stdscr = curses.initscr()
|
|
48
|
+
curses.start_color()
|
|
49
|
+
curses.noecho()
|
|
50
|
+
curses.cbreak()
|
|
51
|
+
curses.curs_set(0)
|
|
52
|
+
self.stdscr.keypad(True)
|
|
53
|
+
curses.mousemask(curses.BUTTON1_RELEASED)
|
|
54
|
+
|
|
55
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
56
|
+
|
|
57
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
58
|
+
curses.nocbreak()
|
|
59
|
+
self.stdscr.keypad(False)
|
|
60
|
+
curses.curs_set(1)
|
|
61
|
+
curses.echo()
|
|
62
|
+
curses.endwin()
|
|
63
|
+
print("Terminal too small! Try 80 columns x 24 rows")
|
|
64
|
+
sys.exit(1)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# Idle, OK, Busy or Alert.
|
|
68
|
+
# gray, green, yellow and red
|
|
69
|
+
|
|
70
|
+
curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_GREEN)
|
|
71
|
+
curses.init_pair(2, curses.COLOR_BLACK, curses.COLOR_YELLOW)
|
|
72
|
+
curses.init_pair(3, curses.COLOR_BLACK, curses.COLOR_RED)
|
|
73
|
+
|
|
74
|
+
# this keeps track of which screen is being displayed,
|
|
75
|
+
# initially start with the messages screen
|
|
76
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
77
|
+
self.screen.show()
|
|
78
|
+
|
|
79
|
+
# this is set to True, to shut down the client
|
|
80
|
+
self._shutdown = False
|
|
81
|
+
# and shutdown routine sets this to True to stop coroutines
|
|
82
|
+
self.stop = False
|
|
83
|
+
# these are set to True when asyncrun is finished
|
|
84
|
+
self.updatescreenstopped = False
|
|
85
|
+
self.getinputstopped = False
|
|
86
|
+
|
|
87
|
+
# list of known device names, this is needed to send
|
|
88
|
+
# BLOB's enabled
|
|
89
|
+
self.devicenames = []
|
|
90
|
+
|
|
91
|
+
# BLOBfiles, is a dictionary of {(devicename,vectorname,membername):filepath}
|
|
92
|
+
self.BLOBfiles = {}
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def color(self, state):
|
|
97
|
+
"Returns curses.color_pair given a state"
|
|
98
|
+
if not curses.has_colors():
|
|
99
|
+
return curses.color_pair(0)
|
|
100
|
+
state = state.lower()
|
|
101
|
+
if state == "ok":
|
|
102
|
+
return curses.color_pair(1)
|
|
103
|
+
elif state == "busy":
|
|
104
|
+
return curses.color_pair(2)
|
|
105
|
+
elif state == "alert":
|
|
106
|
+
return curses.color_pair(3)
|
|
107
|
+
return curses.color_pair(0)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def connected(self):
|
|
111
|
+
return self.client.connected
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def shutdown(self):
|
|
115
|
+
self._shutdown = True
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def _checkshutdown(self):
|
|
119
|
+
"If self._shutdown becomes True, shutdown"
|
|
120
|
+
while not self._shutdown:
|
|
121
|
+
await asyncio.sleep(0)
|
|
122
|
+
await self.client.report("Shutting down client - please wait")
|
|
123
|
+
self.client.shutdown()
|
|
124
|
+
while not self.client.stopped:
|
|
125
|
+
await asyncio.sleep(0)
|
|
126
|
+
# now stop co-routines
|
|
127
|
+
self.stop = True
|
|
128
|
+
while (not self.updatescreenstopped) and (not self.getinputstopped):
|
|
129
|
+
await asyncio.sleep(0)
|
|
130
|
+
# async tasks finished, clear up the terminal
|
|
131
|
+
curses.nocbreak()
|
|
132
|
+
self.stdscr.keypad(False)
|
|
133
|
+
curses.curs_set(1)
|
|
134
|
+
curses.echo()
|
|
135
|
+
curses.endwin()
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
async def updatescreen(self):
|
|
139
|
+
"Update while events are being received"
|
|
140
|
+
try:
|
|
141
|
+
while not self.stop:
|
|
142
|
+
await asyncio.sleep(0)
|
|
143
|
+
if isinstance(self.screen, windows.TooSmall):
|
|
144
|
+
continue
|
|
145
|
+
if not self.connected:
|
|
146
|
+
if isinstance(self.screen, windows.MessagesScreen):
|
|
147
|
+
# set disconnected status and focus on the quit button
|
|
148
|
+
if not self.screen.disconnectionflag:
|
|
149
|
+
self.devicenames.clear()
|
|
150
|
+
self.screen.showunconnected() # sets disconnectionflag
|
|
151
|
+
else:
|
|
152
|
+
# when not connected, show messages screen
|
|
153
|
+
self.screen.close("Messages")
|
|
154
|
+
continue
|
|
155
|
+
# act when an event is received
|
|
156
|
+
try:
|
|
157
|
+
event = self.eventque.pop()
|
|
158
|
+
except IndexError:
|
|
159
|
+
# no event received, so do not update screen
|
|
160
|
+
continue
|
|
161
|
+
if isinstance(event, VectorTimeOut) and (event.devicename == self.screen.devicename):
|
|
162
|
+
if isinstance(self.screen, windows.ChooseVectorScreen):
|
|
163
|
+
self.screen.timeout(event)
|
|
164
|
+
continue
|
|
165
|
+
if isinstance(self.screen, windows.VectorScreen) and (self.screen.vectorname == event.vectorname):
|
|
166
|
+
self.screen.timeout(event)
|
|
167
|
+
continue
|
|
168
|
+
if hasattr(event, 'devicename'):
|
|
169
|
+
# if this is a new device, update it with BLOB status
|
|
170
|
+
if event.devicename and (event.devicename not in self.devicenames):
|
|
171
|
+
if event.devicename in self.client:
|
|
172
|
+
device = self.client[event.devicename]
|
|
173
|
+
if device.enable:
|
|
174
|
+
# new devicename
|
|
175
|
+
self.devicenames.append(event.devicename)
|
|
176
|
+
if self.blobenabled:
|
|
177
|
+
self.client.send_enableBLOB('Also', event.devicename)
|
|
178
|
+
else:
|
|
179
|
+
self.client.send_enableBLOB('Never', event.devicename)
|
|
180
|
+
# If the event is a received BLOB, save it to the BLOB Folder
|
|
181
|
+
if isinstance(event, setBLOBVector):
|
|
182
|
+
# make filename from timestamp
|
|
183
|
+
timestampstring = event.timestamp.strftime('%Y%m%d_%H_%M_%S')
|
|
184
|
+
for membername, membervalue in event.items():
|
|
185
|
+
sizeformat = event.sizeformat[membername]
|
|
186
|
+
filename = membername + "_" + timestampstring + sizeformat[1]
|
|
187
|
+
counter = 0
|
|
188
|
+
while True:
|
|
189
|
+
filepath = self.blobfolder / filename
|
|
190
|
+
if filepath.exists():
|
|
191
|
+
# append a digit to the filename
|
|
192
|
+
counter += 1
|
|
193
|
+
filename = membername + "_" + timestampstring + "_" + str(counter) + sizeformat[1]
|
|
194
|
+
else:
|
|
195
|
+
# filepath does not exist, so a new file with this filepath can be created
|
|
196
|
+
break
|
|
197
|
+
filepath.write_bytes(membervalue)
|
|
198
|
+
# record the filepath
|
|
199
|
+
self.BLOBfiles[(event.devicename, event.vectorname, membername)] = filepath
|
|
200
|
+
if isinstance(self.screen, windows.MessagesScreen):
|
|
201
|
+
self.screen.update(event)
|
|
202
|
+
continue
|
|
203
|
+
if isinstance(self.screen, windows.DevicesScreen):
|
|
204
|
+
self.screen.update(event)
|
|
205
|
+
continue
|
|
206
|
+
if isinstance(self.screen, windows.EnableBLOBsScreen):
|
|
207
|
+
self.screen.update(event)
|
|
208
|
+
continue
|
|
209
|
+
if event.devicename != self.screen.devicename:
|
|
210
|
+
# the remaining screens are only affected if the event devicename
|
|
211
|
+
# is the device they refer to
|
|
212
|
+
continue
|
|
213
|
+
if isinstance(event, delProperty):
|
|
214
|
+
if event.vectorname is None:
|
|
215
|
+
# the whole device is disabled,
|
|
216
|
+
if event.devicename and (event.devicename in self.devicenames):
|
|
217
|
+
self.devicenames.remove(event.devicename)
|
|
218
|
+
# show devicesscreen
|
|
219
|
+
self.screen.close("Devices")
|
|
220
|
+
continue
|
|
221
|
+
if isinstance(self.screen, windows.ChooseVectorScreen):
|
|
222
|
+
# one vector has been disabled, update the ChooseVectorScreen
|
|
223
|
+
self.screen.update(event)
|
|
224
|
+
continue
|
|
225
|
+
if isinstance(self.screen, windows.VectorScreen) and (self.screen.vectorname == event.vectorname):
|
|
226
|
+
# This vector has been disabled, show ChooseVectorScreen
|
|
227
|
+
self.screen.close("Vectors")
|
|
228
|
+
continue
|
|
229
|
+
continue
|
|
230
|
+
# so its not a delete property
|
|
231
|
+
if isinstance(self.screen, windows.ChooseVectorScreen):
|
|
232
|
+
self.screen.update(event)
|
|
233
|
+
continue
|
|
234
|
+
if isinstance(self.screen, windows.VectorScreen) and (self.screen.vectorname == event.vectorname):
|
|
235
|
+
# The event refers to this vector
|
|
236
|
+
self.screen.update(event)
|
|
237
|
+
|
|
238
|
+
except asyncio.CancelledError:
|
|
239
|
+
self._shutdown = True
|
|
240
|
+
raise
|
|
241
|
+
except Exception as e:
|
|
242
|
+
widgets.ERRORDATA.append(TBE.from_exception(e))
|
|
243
|
+
self._shutdown = True
|
|
244
|
+
finally:
|
|
245
|
+
self.updatescreenstopped = True
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
async def getinput(self):
|
|
249
|
+
try:
|
|
250
|
+
while not self.stop:
|
|
251
|
+
await asyncio.sleep(0)
|
|
252
|
+
if isinstance(self.screen, windows.TooSmall):
|
|
253
|
+
result = await self.screen.inputs()
|
|
254
|
+
if result == "Resize":
|
|
255
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
256
|
+
if self.maxrows < 10 or self.maxcols < 40:
|
|
257
|
+
self.shutdown()
|
|
258
|
+
continue
|
|
259
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
260
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
261
|
+
self.screen.show()
|
|
262
|
+
continue
|
|
263
|
+
# so resize has increased to proper size
|
|
264
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
265
|
+
self.screen.show()
|
|
266
|
+
continue
|
|
267
|
+
if result == "Quit":
|
|
268
|
+
self._shutdown = True
|
|
269
|
+
break
|
|
270
|
+
|
|
271
|
+
if isinstance(self.screen, windows.MessagesScreen):
|
|
272
|
+
result = await self.screen.inputs()
|
|
273
|
+
if result == "Resize":
|
|
274
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
275
|
+
if self.maxrows < 16 or self.maxcols < 40:
|
|
276
|
+
self.shutdown()
|
|
277
|
+
continue
|
|
278
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
279
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
280
|
+
self.screen.show()
|
|
281
|
+
continue
|
|
282
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
283
|
+
self.screen.show()
|
|
284
|
+
continue
|
|
285
|
+
if result == "Quit":
|
|
286
|
+
self._shutdown = True
|
|
287
|
+
break
|
|
288
|
+
if result == "Devices":
|
|
289
|
+
self.screen = windows.DevicesScreen(self.stdscr, self)
|
|
290
|
+
self.screen.show()
|
|
291
|
+
continue
|
|
292
|
+
if result == "EnableBLOBs":
|
|
293
|
+
self.screen = windows.EnableBLOBsScreen(self.stdscr, self)
|
|
294
|
+
self.screen.show()
|
|
295
|
+
continue
|
|
296
|
+
if isinstance(self.screen, windows.EnableBLOBsScreen):
|
|
297
|
+
result = await self.screen.inputs()
|
|
298
|
+
if result == "Resize":
|
|
299
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
300
|
+
if self.maxrows < 16 or self.maxcols < 40:
|
|
301
|
+
self.shutdown()
|
|
302
|
+
continue
|
|
303
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
304
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
305
|
+
self.screen.show()
|
|
306
|
+
continue
|
|
307
|
+
self.screen = windows.EnableBLOBsScreen(self.stdscr, self)
|
|
308
|
+
self.screen.show()
|
|
309
|
+
continue
|
|
310
|
+
if result == "Quit":
|
|
311
|
+
self._shutdown = True
|
|
312
|
+
break
|
|
313
|
+
if result == "Messages":
|
|
314
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
315
|
+
self.screen.show()
|
|
316
|
+
continue
|
|
317
|
+
if result == "Devices":
|
|
318
|
+
self.screen = windows.DevicesScreen(self.stdscr, self)
|
|
319
|
+
self.screen.show()
|
|
320
|
+
continue
|
|
321
|
+
if isinstance(self.screen, windows.DevicesScreen):
|
|
322
|
+
result = await self.screen.inputs()
|
|
323
|
+
if result == "Resize":
|
|
324
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
325
|
+
if self.maxrows < 16 or self.maxcols < 40:
|
|
326
|
+
self.shutdown()
|
|
327
|
+
continue
|
|
328
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
329
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
330
|
+
self.screen.show()
|
|
331
|
+
continue
|
|
332
|
+
self.screen = windows.DevicesScreen(self.stdscr, self)
|
|
333
|
+
self.screen.show()
|
|
334
|
+
continue
|
|
335
|
+
if result == "Quit":
|
|
336
|
+
self._shutdown = True
|
|
337
|
+
break
|
|
338
|
+
if result == "Messages":
|
|
339
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
340
|
+
self.screen.show()
|
|
341
|
+
continue
|
|
342
|
+
devices = {devicename.lower():device for devicename, device in self.client.items() if device.enable}
|
|
343
|
+
if result in devices:
|
|
344
|
+
devicename = devices[result].devicename
|
|
345
|
+
self.screen = windows.ChooseVectorScreen(self.stdscr, self, devicename)
|
|
346
|
+
self.screen.show()
|
|
347
|
+
continue
|
|
348
|
+
if isinstance(self.screen, windows.ChooseVectorScreen):
|
|
349
|
+
result = await self.screen.inputs()
|
|
350
|
+
if result == "Resize":
|
|
351
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
352
|
+
if self.maxrows < 16 or self.maxcols < 40:
|
|
353
|
+
self.shutdown()
|
|
354
|
+
continue
|
|
355
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
356
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
357
|
+
self.screen.show()
|
|
358
|
+
continue
|
|
359
|
+
self.screen = windows.ChooseVectorScreen(self.stdscr, self, self.screen.devicename, group=self.screen.groupwin.active)
|
|
360
|
+
self.screen.show()
|
|
361
|
+
continue
|
|
362
|
+
if result == "Quit":
|
|
363
|
+
self._shutdown = True
|
|
364
|
+
break
|
|
365
|
+
if result == "Messages":
|
|
366
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
367
|
+
self.screen.show()
|
|
368
|
+
continue
|
|
369
|
+
if result == "Devices":
|
|
370
|
+
self.screen = windows.DevicesScreen(self.stdscr, self)
|
|
371
|
+
self.screen.show()
|
|
372
|
+
continue
|
|
373
|
+
if result == "Vectors":
|
|
374
|
+
# get device, vector and show VectorScreen
|
|
375
|
+
self.screen = windows.VectorScreen(self.stdscr, self, self.screen.devicename, self.screen.vectorname)
|
|
376
|
+
self.screen.show()
|
|
377
|
+
continue
|
|
378
|
+
if isinstance(self.screen, windows.VectorScreen):
|
|
379
|
+
result = await self.screen.inputs()
|
|
380
|
+
if result == "Resize":
|
|
381
|
+
self.maxrows, self.maxcols = self.stdscr.getmaxyx()
|
|
382
|
+
if self.maxrows < 16 or self.maxcols < 40:
|
|
383
|
+
self.shutdown()
|
|
384
|
+
continue
|
|
385
|
+
if self.maxrows < MINROWS or self.maxcols < MINCOLS:
|
|
386
|
+
self.screen = windows.TooSmall(self.stdscr, self)
|
|
387
|
+
self.screen.show()
|
|
388
|
+
continue
|
|
389
|
+
self.screen = windows.VectorScreen(self.stdscr, self, self.screen.devicename, self.screen.vectorname)
|
|
390
|
+
self.screen.show()
|
|
391
|
+
continue
|
|
392
|
+
if result == "Quit":
|
|
393
|
+
self._shutdown = True
|
|
394
|
+
break
|
|
395
|
+
if result == "Messages":
|
|
396
|
+
self.screen = windows.MessagesScreen(self.stdscr, self)
|
|
397
|
+
self.screen.show()
|
|
398
|
+
continue
|
|
399
|
+
if result == "Devices":
|
|
400
|
+
self.screen = windows.DevicesScreen(self.stdscr, self)
|
|
401
|
+
self.screen.show()
|
|
402
|
+
continue
|
|
403
|
+
if result == "Vectors":
|
|
404
|
+
self.screen = windows.ChooseVectorScreen(self.stdscr, self, self.screen.devicename, group=self.screen.vector.group)
|
|
405
|
+
self.screen.show()
|
|
406
|
+
continue
|
|
407
|
+
|
|
408
|
+
except asyncio.CancelledError:
|
|
409
|
+
self._shutdown = True
|
|
410
|
+
raise
|
|
411
|
+
except Exception as e:
|
|
412
|
+
widgets.ERRORDATA.append(TBE.from_exception(e))
|
|
413
|
+
self._shutdown = True
|
|
414
|
+
finally:
|
|
415
|
+
self.getinputstopped = True
|
|
416
|
+
|
|
417
|
+
|
|
418
|
+
def send_enableBLOB(self):
|
|
419
|
+
"Sends Also to enable blobs for all devices"
|
|
420
|
+
if not self.blobenabled:
|
|
421
|
+
return
|
|
422
|
+
for devicename,device in self.client.items():
|
|
423
|
+
if device.enable:
|
|
424
|
+
self.client.send_enableBLOB('Also', devicename)
|
|
425
|
+
|
|
426
|
+
def send_disableBLOB(self):
|
|
427
|
+
"Sends Never to disable blobs for all devices"
|
|
428
|
+
if self.blobenabled:
|
|
429
|
+
return
|
|
430
|
+
for devicename,device in self.client.items():
|
|
431
|
+
if device.enable:
|
|
432
|
+
self.client.send_enableBLOB('Never', devicename)
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
async def asyncrun(self):
|
|
436
|
+
"""Gathers tasks to be run simultaneously"""
|
|
437
|
+
self.stop = False
|
|
438
|
+
await asyncio.gather(self.updatescreen(), self.getinput(), self._checkshutdown())
|