forked from joellama/shelyak_control
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinstrument.py
146 lines (118 loc) · 4.38 KB
/
instrument.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from abc import ABCMeta, abstractmethod
import socketio
value = "Dummy value"
host = "http://0.0.0.0:5000"
class Instrument(metaclass=ABCMeta):
"""
Interface for the standard Instrument to be implemented by other instruments
Note: do not forget to register new classes with the decorator: @Instrument.register
else, the instrument will fail to instantiate
Attributes:
-----------
status_dictionary: dict
Starting values for statuses important for usage.
Ex: the status of lamps for a spectrograph, whether on or off
sio: socketio.Client
Socket connection to be used when communicating with the backend
server
id: int
The unique id given to the instrument upon startup to be used in
updates.
Methods:
--------
get_instrument_name(): str
How the instrument acquires its name for identification with the
server
Note: Must be implemented in subclasses
update_status(update_dict): None
Updates the backend with the given dictionary via the instantiated
socket connection
callbacks(): None
Inside this function is a list of events that the instrument should
be listening for.
Note: Must be implemented in subclasses
"""
# should be set to default values
status_dictionary = {
"status_name1": {"value": value, "color": value},
"status_name2": {"value": value, "color": value},
}
sio = socketio.Client(
request_timeout=60,
logger=True,
engineio_logger=True,
)
def __init__(self):
"""
Initializes the socket, id, statuses in the backend, and the callbacks
that subclasses will implement. The super for this function must
be called for the normal operation of this instrument.
"""
self.sio.connect(host)
self.name = self.get_instrument_name()
self.id = self.sio.call("get_instrument_id", self.name)
self.update_status(self.status_dictionary)
self.callbacks()
self.sio.wait()
def __del__(self):
"""
Disconnects the socket if ever the Instrument is de-instantiated
"""
self.sio.disconnect()
@abstractmethod
def get_instrument_name(self):
"""
Should be a programmatic method of collecting the name of a given
instrument.
"""
pass
def update_status(self, update_dict):
"""
Sends an emmision to the backend with the new statuses of a given
instrument, using the id as an identifier so that the correct statuses
are updated.
Note: The format of these statuses should be the same as the initial
status dictionary
Parameters:
----------
update_dict: dict
the dictionary of updates to the instruments statuses to
be sent to the backend device
"""
self.sio.emit("update_status", (self.id, update_dict))
@staticmethod
def make_num_status(num_vals: dict):
"""
Format a dictionary of numerical values to provide the desired color.
Note: The format of these statuses should be the same as the initial
status dictionary
Parameters:
----------
TODO:
"""
out_vals: dict = {}
for status_name, status_val in num_vals.items():
out_vals[status_name] = {"value": status_val, "color": "primary"}
return out_vals
@abstractmethod
def callbacks(self):
"""
Initializes the endpoints that the backend might call that this
instrument will want to listen for. As many of these can be implemented.
NOTE: Use the documentation for the socketio.Client class for more
information about how these events are created. However,
one example is given below.
NOTE: below is an example of instantiating an event for sio
@Instrument.sio.on('name')
def function_name(self):
pass
"""
# put all sio endpoints in this function when implemented
pass
"""
Each file should have a main method that runs the this code, plus whatever other code to be implemented
"""
def main():
instrument = Instrument()
if __name__ == "__main__":
main()