This example file shows how to create a server that connects to an instrument.
This example file shows how to create a server that connects to an instrument.It can recieve TCP commands from a client to trigger experiments and send data back to the client.
1"""! @example tcpServer.py
2@brief This example file shows how to create a server that connects to an instrument.
3
4It can recieve TCP commands from a client to trigger experiments and send data back to the client.
5"""
6import os
7import socket
8import threading
9from PySide6.QtWidgets import QApplication
10from SquidstatPyLibrary import AisDeviceTracker
11from SquidstatPyLibrary import AisExperiment
12from SquidstatPyLibrary import AisOpenCircuitElement
13from SquidstatPyLibrary import AisErrorCode
14
15
16HOST = 'localhost'
17PORT = 12345
18
19
20SQUIDCOMPORT = "COM1"
21SQUIDNAME = "Plus2000"
22
23
24app = QApplication([])
25activeSockets = []
26
27
28def start_ocp_experiment(handler, durationSec=60):
29
32
33 success = experiment.appendElement(ocpElement, 1)
34 if not success:
35 print("Error adding element to experiment")
36 return error.ExperimentNotUploaded
37
38
39 error = handler.uploadExperimentToChannel(0, experiment)
40 if error.value() != AisErrorCode.ErrorCode.Success:
41 return error
42
43
44 return(handler.startUploadedExperiment(0))
45
46
47def command_to_device(command, handler):
48
49 splitCommand = command.split(" ")
50 action = splitCommand[0]
51 actionArg = 0
52 if(len(splitCommand) > 1):
53 try:
54 actionArg = int(splitCommand[1])
55 except:
56 actionArg = 0
57
58
59 response = None
60 if action == 'startExperiment':
61 response = start_ocp_experiment(handler, actionArg)
62 elif action == 'stopExperiment':
63 response = handler.stopExperiment(0)
64 else:
65
66 pass
67 return response
68
69
70def handle_command(command, handler, client_socket):
71
72 responseMsg = "Unknown Command"
73 response = command_to_device(command, handler)
74 if(response != None):
75 responseMsg = response.message()
76 response = "{}".format(responseMsg)
77 client_socket.send(response.encode())
78
79
80def handle_client(handler, client_socket):
81 print("Client connected")
82
83 while True:
84
85 try:
86 data = client_socket.recv(1024).decode()
87 except ConnectionResetError:
88 break
89
90
91 if not data:
92 break
93
94
95 handle_command(data, handler, client_socket)
96
97
98 handler.activeDCDataReady.disconnect()
99 handler.activeACDataReady.disconnect()
100 handler.experimentNewElementStarting.disconnect()
101 handler.experimentStopped.disconnect()
102 command_to_device("stopExperiment", handler)
103
104 client_socket.close()
105 print("Client disconnected")
106 os._exit(1)
107
108
109def send_data_to_client(client_socket, event_type, data):
110 if event_type == "DCData":
111 message = "timestamp: {:.9f}, workingElectrodeVoltage: {:.9f}".format(data.timestamp, data.workingElectrodeVoltage)
112 elif event_type == "ACData":
113 message = "frequency: {:.9f}, absoluteImpedance: {:.9f}, phaseAngle: {:.9f}".format(data.frequency, data.absoluteImpedance, data.phaseAngle)
114 elif event_type == "NewElement":
115 message = "New Node beginning: {}, step number: {}, step sub: {}".format(data.stepName, data.stepNumber, data.substepNumber)
116 elif event_type == "ExperimentCompleted":
117 message = "Experiment Completed: {}".format(data)
118 else:
119 return
120
121 client_socket.send(message.encode())
122
123def terminate_program():
124 print("Press <CTRL>+c to close the server")
125 try:
126 while True:
127 input()
128 except (EOFError, KeyboardInterrupt):
129 pass
130 for socket in activeSockets:
131 socket.close()
132 app.quit()
133 os._exit(1)
134
135
136
137print(f"Attempting to connect to the Squidstat {SQUIDNAME} on {SQUIDCOMPORT}...")
139tracker.newDeviceConnected.connect(lambda deviceName: print("Device is Connected: %s" % deviceName))
140error = tracker.connectToDeviceOnComPort(SQUIDCOMPORT)
141
142if error.value() != AisErrorCode.ErrorCode.Success:
143 print(error.message())
144 exit()
145
146
147handler = tracker.getInstrumentHandler(SQUIDNAME)
148print("Connection successful\n")
149
150
151print("Starting server...")
152server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
153activeSockets.append(server_socket)
154server_socket.bind((HOST, PORT))
155
156
157server_socket.listen(1)
158
159print("Server started successfully. Waiting for client connection...")
160
161terminal_thread = threading.Thread(target=terminate_program)
162terminal_thread.start()
163
164
165client_socket, client_address = server_socket.accept()
166activeSockets.append(client_socket)
167
168
169handler.activeDCDataReady.connect(lambda channel, data: send_data_to_client(client_socket, "DCData", data))
170handler.activeACDataReady.connect(lambda channel, data: send_data_to_client(client_socket, "ACData", data))
171handler.experimentNewElementStarting.connect(lambda channel, data: send_data_to_client(client_socket, "NewElement", data))
172handler.experimentStopped.connect(lambda channel: send_data_to_client(client_socket, "ExperimentCompleted", channel))
173
174
175listening_thread = threading.Thread(target=handle_client, args=(handler, client_socket))
176listening_thread.start()
177
178
179app.exec()
static AisDeviceTracker * Instance()
get the instance of the device tracker.
this class is used to create custom experiments. A custom experiment contains one or more elements....
Definition AisExperiment.h:22
This experiment observes the open circuit potential of the working electrode for a specific period of...
Definition AisOpenCircuitElement.h:18