mx-bluesky 1.4.0__py3-none-any.whl → 1.4.1a0__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.
- mx_bluesky/_version.py +2 -2
- mx_bluesky/beamlines/i04/thawing_plan.py +1 -1
- mx_bluesky/beamlines/i24/serial/dcid.py +19 -21
- mx_bluesky/beamlines/i24/serial/extruder/i24ssx_Extruder_Collect_py3v2.py +2 -2
- mx_bluesky/beamlines/i24/serial/fixed_target/FT-gui-edm/DiamondChipI24-py3v1.edl +1 -4
- mx_bluesky/beamlines/i24/serial/fixed_target/ft_utils.py +0 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Collect_py3v1.py +14 -24
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Manager_py3v1.py +18 -76
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_StartUp_py3v1.py +0 -199
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_moveonclick.py +4 -6
- mx_bluesky/beamlines/i24/serial/log.py +1 -1
- mx_bluesky/beamlines/i24/serial/parameters/constants.py +0 -1
- mx_bluesky/beamlines/i24/serial/run_fixed_target.sh +4 -3
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_beamline.py +78 -80
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_detector.py +1 -2
- mx_bluesky/beamlines/i24/serial/setup_beamline/setup_zebra_plans.py +24 -26
- mx_bluesky/beamlines/i24/serial/write_nexus.py +11 -11
- mx_bluesky/common/external_interaction/config_server.py +46 -0
- mx_bluesky/common/parameters/components.py +52 -15
- mx_bluesky/common/parameters/constants.py +6 -1
- mx_bluesky/common/parameters/gridscan.py +94 -0
- mx_bluesky/{hyperion → common}/parameters/robot_load.py +2 -2
- mx_bluesky/common/plans/do_fgs.py +2 -2
- mx_bluesky/common/utils/log.py +2 -0
- mx_bluesky/hyperion/__main__.py +2 -1
- mx_bluesky/hyperion/device_setup_plans/setup_panda.py +4 -4
- mx_bluesky/hyperion/device_setup_plans/setup_zebra.py +1 -1
- mx_bluesky/hyperion/experiment_plans/__init__.py +4 -0
- mx_bluesky/hyperion/experiment_plans/change_aperture_then_move_plan.py +83 -0
- mx_bluesky/hyperion/experiment_plans/common/xrc_result.py +47 -0
- mx_bluesky/hyperion/experiment_plans/experiment_registry.py +9 -9
- mx_bluesky/hyperion/experiment_plans/flyscan_xray_centre_plan.py +131 -89
- mx_bluesky/hyperion/experiment_plans/grid_detect_then_xray_centre_plan.py +50 -18
- mx_bluesky/hyperion/experiment_plans/load_centre_collect_full_plan.py +52 -10
- mx_bluesky/hyperion/experiment_plans/oav_grid_detection_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/oav_snapshot_plan.py +3 -9
- mx_bluesky/hyperion/experiment_plans/optimise_attenuation_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/pin_centre_then_xray_centre_plan.py +36 -17
- mx_bluesky/hyperion/experiment_plans/pin_tip_centring_plan.py +2 -2
- mx_bluesky/hyperion/experiment_plans/robot_load_and_change_energy.py +6 -10
- mx_bluesky/hyperion/experiment_plans/robot_load_then_centre_plan.py +46 -11
- mx_bluesky/hyperion/experiment_plans/rotation_scan_plan.py +18 -3
- mx_bluesky/hyperion/experiment_plans/set_energy_plan.py +2 -3
- mx_bluesky/hyperion/external_interaction/callbacks/common/abstract_event.py +66 -0
- mx_bluesky/hyperion/external_interaction/callbacks/grid_detection_callback.py +15 -15
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/ispyb_callback.py +3 -1
- mx_bluesky/hyperion/external_interaction/callbacks/rotation/nexus_callback.py +5 -3
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/ispyb_callback.py +5 -2
- mx_bluesky/hyperion/external_interaction/callbacks/xray_centre/nexus_callback.py +5 -4
- mx_bluesky/hyperion/external_interaction/config_server.py +8 -37
- mx_bluesky/hyperion/external_interaction/ispyb/exp_eye_store.py +1 -1
- mx_bluesky/hyperion/parameters/components.py +4 -9
- mx_bluesky/hyperion/parameters/constants.py +0 -1
- mx_bluesky/hyperion/parameters/gridscan.py +33 -76
- mx_bluesky/hyperion/parameters/load_centre_collect.py +14 -9
- mx_bluesky/hyperion/parameters/rotation.py +15 -6
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/METADATA +35 -34
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/RECORD +62 -58
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/WHEEL +1 -1
- mx_bluesky/beamlines/i24/serial/fixed_target/i24ssx_Chip_Mapping_py3v1.py +0 -150
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/LICENSE +0 -0
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/entry_points.txt +0 -0
- {mx_bluesky-1.4.0.dist-info → mx_bluesky-1.4.1a0.dist-info}/top_level.txt +0 -0
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
Startup utilities for chip
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import os
|
|
6
5
|
import string
|
|
7
|
-
import time
|
|
8
6
|
from pathlib import Path
|
|
9
7
|
|
|
10
|
-
import numpy as np
|
|
11
|
-
|
|
12
8
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import ChipType
|
|
13
9
|
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER, log_on_entry
|
|
14
10
|
from mx_bluesky.beamlines.i24.serial.parameters import (
|
|
@@ -16,7 +12,6 @@ from mx_bluesky.beamlines.i24.serial.parameters import (
|
|
|
16
12
|
get_chip_format,
|
|
17
13
|
)
|
|
18
14
|
from mx_bluesky.beamlines.i24.serial.parameters.constants import (
|
|
19
|
-
HEADER_FILES_PATH,
|
|
20
15
|
PARAM_FILE_NAME,
|
|
21
16
|
PARAM_FILE_PATH_FT,
|
|
22
17
|
)
|
|
@@ -45,31 +40,6 @@ def fiducials(chip_type: int):
|
|
|
45
40
|
return fiducial_list
|
|
46
41
|
|
|
47
42
|
|
|
48
|
-
def get_xy(addr: str, chip_type: ChipType):
|
|
49
|
-
entry = addr.split("_")[-2:]
|
|
50
|
-
R, C = entry[0][0], entry[0][1]
|
|
51
|
-
r2, c2 = entry[1][0], entry[1][1]
|
|
52
|
-
blockR = string.ascii_uppercase.index(R)
|
|
53
|
-
blockC = int(C) - 1
|
|
54
|
-
lowercase_list = list(string.ascii_lowercase + string.ascii_uppercase + "0")
|
|
55
|
-
windowR = lowercase_list.index(r2)
|
|
56
|
-
windowC = lowercase_list.index(c2)
|
|
57
|
-
|
|
58
|
-
chip_params = get_chip_format(chip_type)
|
|
59
|
-
|
|
60
|
-
x = (
|
|
61
|
-
(blockC * chip_params.b2b_horz)
|
|
62
|
-
+ (blockC * (chip_params.x_num_steps - 1) * chip_params.x_step_size)
|
|
63
|
-
+ (windowC * chip_params.x_step_size)
|
|
64
|
-
)
|
|
65
|
-
y = (
|
|
66
|
-
(blockR * chip_params.b2b_vert)
|
|
67
|
-
+ (blockR * (chip_params.y_num_steps - 1) * chip_params.y_step_size)
|
|
68
|
-
+ (windowR * chip_params.y_step_size)
|
|
69
|
-
)
|
|
70
|
-
return x, y
|
|
71
|
-
|
|
72
|
-
|
|
73
43
|
def pathli(l_in=None, way="typewriter", reverse=False):
|
|
74
44
|
if l_in is None:
|
|
75
45
|
l_in = []
|
|
@@ -147,172 +117,3 @@ def get_alphanumeric(chip_type: ChipType):
|
|
|
147
117
|
alphanumeric_list.append(block + "_" + window)
|
|
148
118
|
SSX_LOGGER.info(f"Length of alphanumeric list = {len(alphanumeric_list)}")
|
|
149
119
|
return alphanumeric_list
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
@log_on_entry
|
|
153
|
-
def get_shot_order(chip_type: ChipType):
|
|
154
|
-
cell_format = get_chip_format(chip_type)
|
|
155
|
-
blk_num = cell_format.x_blocks
|
|
156
|
-
wnd_num = cell_format.x_num_steps
|
|
157
|
-
uppercase_list = list(string.ascii_uppercase)[:blk_num]
|
|
158
|
-
number_list = [str(x) for x in range(1, blk_num + 1)]
|
|
159
|
-
lowercase_list = list(string.ascii_lowercase + string.ascii_uppercase + "0")[
|
|
160
|
-
:wnd_num
|
|
161
|
-
]
|
|
162
|
-
|
|
163
|
-
block_list = zippum([uppercase_list, "snake", 0], [number_list, "expand", 0])
|
|
164
|
-
window_dn = zippum([lowercase_list, "expand", 0], [lowercase_list, "snake", 0])
|
|
165
|
-
window_up = zippum([lowercase_list, "expand", 1], [lowercase_list, "snake", 0])
|
|
166
|
-
|
|
167
|
-
switch = 0
|
|
168
|
-
count = 0
|
|
169
|
-
collect_list = []
|
|
170
|
-
for block in block_list:
|
|
171
|
-
if switch == 0:
|
|
172
|
-
for window in window_dn:
|
|
173
|
-
collect_list.append(block + "_" + window)
|
|
174
|
-
count += 1
|
|
175
|
-
if count == blk_num:
|
|
176
|
-
count = 0
|
|
177
|
-
switch = 1
|
|
178
|
-
else:
|
|
179
|
-
for window in window_up:
|
|
180
|
-
collect_list.append(block + "_" + window)
|
|
181
|
-
count += 1
|
|
182
|
-
if count == blk_num:
|
|
183
|
-
count = 0
|
|
184
|
-
switch = 0
|
|
185
|
-
|
|
186
|
-
SSX_LOGGER.info(f"Length of collect list = {len(collect_list)}")
|
|
187
|
-
return collect_list
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
@log_on_entry
|
|
191
|
-
def write_file(
|
|
192
|
-
location: str = "i24",
|
|
193
|
-
suffix: str = ".addr",
|
|
194
|
-
order: str = "alphanumeric",
|
|
195
|
-
param_file_path: Path = PARAM_FILE_PATH_FT,
|
|
196
|
-
save_path: Path = HEADER_FILES_PATH,
|
|
197
|
-
):
|
|
198
|
-
if location == "i24":
|
|
199
|
-
params = read_parameter_file(param_file_path)
|
|
200
|
-
else:
|
|
201
|
-
msg = f"Unknown location, {location}"
|
|
202
|
-
SSX_LOGGER.error(msg)
|
|
203
|
-
raise ValueError(msg)
|
|
204
|
-
chip_file_path = save_path / f"chips/{params.directory}/{params.filename}{suffix}"
|
|
205
|
-
|
|
206
|
-
fiducial_list = fiducials(params.chip.chip_type.value)
|
|
207
|
-
|
|
208
|
-
if order == "alphanumeric":
|
|
209
|
-
addr_list = get_alphanumeric(params.chip.chip_type)
|
|
210
|
-
elif order == "shot":
|
|
211
|
-
addr_list = get_shot_order(params.chip.chip_type)
|
|
212
|
-
else:
|
|
213
|
-
raise ValueError(f"{order=} unrecognised")
|
|
214
|
-
|
|
215
|
-
with open(chip_file_path, "a") as g:
|
|
216
|
-
for addr in addr_list:
|
|
217
|
-
xtal_name = "_".join([params.filename, addr])
|
|
218
|
-
(x, y) = get_xy(xtal_name, params.chip.chip_type)
|
|
219
|
-
if addr in fiducial_list:
|
|
220
|
-
pres = "0"
|
|
221
|
-
else:
|
|
222
|
-
if "rand" in suffix:
|
|
223
|
-
pres = str(np.random.randint(2))
|
|
224
|
-
else:
|
|
225
|
-
pres = "-1"
|
|
226
|
-
line = "\t".join([xtal_name, str(x), str(y), "0.0", pres]) + "\n"
|
|
227
|
-
g.write(line)
|
|
228
|
-
|
|
229
|
-
SSX_LOGGER.info(f"Write {chip_file_path} completed")
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
@log_on_entry
|
|
233
|
-
def check_files(
|
|
234
|
-
location: str,
|
|
235
|
-
suffix_list: list[str],
|
|
236
|
-
param_file_path: Path | str = PARAM_FILE_PATH_FT,
|
|
237
|
-
save_path: Path = HEADER_FILES_PATH,
|
|
238
|
-
):
|
|
239
|
-
if location == "i24":
|
|
240
|
-
params = read_parameter_file(param_file_path)
|
|
241
|
-
else:
|
|
242
|
-
msg = f"Unknown location, {location}"
|
|
243
|
-
SSX_LOGGER.error(msg)
|
|
244
|
-
raise ValueError(msg)
|
|
245
|
-
chip_file_path = save_path / f"chips/{params.directory}/{params.filename}"
|
|
246
|
-
|
|
247
|
-
try:
|
|
248
|
-
os.stat(chip_file_path)
|
|
249
|
-
except Exception:
|
|
250
|
-
os.makedirs(chip_file_path)
|
|
251
|
-
for suffix in suffix_list:
|
|
252
|
-
full_fid = chip_file_path.with_suffix(suffix)
|
|
253
|
-
if full_fid.is_file():
|
|
254
|
-
time_str = time.strftime("%Y%m%d_%H%M%S_")
|
|
255
|
-
timestamp_fid = ( # noqa: F841
|
|
256
|
-
full_fid.parent / f"{time_str}_{params.filename}{full_fid.suffix}"
|
|
257
|
-
)
|
|
258
|
-
# FIXME hack / fix. Actually move the file
|
|
259
|
-
SSX_LOGGER.info(f"File {full_fid} Already Exists")
|
|
260
|
-
SSX_LOGGER.debug("Check files done")
|
|
261
|
-
return 1
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
@log_on_entry
|
|
265
|
-
def write_headers(
|
|
266
|
-
location: str,
|
|
267
|
-
suffix_list: list[str],
|
|
268
|
-
param_file_path: Path = PARAM_FILE_PATH_FT,
|
|
269
|
-
save_path: Path = HEADER_FILES_PATH,
|
|
270
|
-
):
|
|
271
|
-
if location == "i24":
|
|
272
|
-
params = read_parameter_file(param_file_path)
|
|
273
|
-
chip_file_path = save_path / f"chips/{params.directory}/{params.filename}"
|
|
274
|
-
|
|
275
|
-
for suffix in suffix_list:
|
|
276
|
-
full_fid = chip_file_path.with_suffix(suffix)
|
|
277
|
-
with open(full_fid, "w") as g:
|
|
278
|
-
g.write(
|
|
279
|
-
"#23456789012345678901234567890123456789012345678901234567890123456789012345678901234567890\n#\n"
|
|
280
|
-
)
|
|
281
|
-
g.write(f"#&i24\tchip_name = {params.filename}\n")
|
|
282
|
-
g.write(f"#&i24\tvisit = {params.visit}\n")
|
|
283
|
-
g.write(f"#&i24\tsub_dir = {params.directory}\n")
|
|
284
|
-
g.write(f"#&i24\tn_exposures = {params.num_exposures}\n")
|
|
285
|
-
g.write(f"#&i24\tchip_type = {params.chip.chip_type.value}\n")
|
|
286
|
-
g.write(f"#&i24\tmap_type = {params.map_type.value}\n")
|
|
287
|
-
g.write(f"#&i24\tpump_repeat = {params.pump_repeat.value}\n")
|
|
288
|
-
g.write(f"#&i24\tpumpexptime = {params.laser_dwell_s}\n")
|
|
289
|
-
g.write(f"#&i24\texptime = {params.laser_delay_s}\n")
|
|
290
|
-
g.write(f"#&i24\tdcdetdist = {params.detector_distance_mm}\n")
|
|
291
|
-
g.write(f"#&i24\tprepumpexptime = {params.pre_pump_exposure_s}\n")
|
|
292
|
-
g.write(f"#&i24\tdet_Type = {params.detector_name}\n")
|
|
293
|
-
g.write("#\n")
|
|
294
|
-
g.write(
|
|
295
|
-
"#XtalAddr XCoord YCoord ZCoord Present Shot Spare04 Spare03 Spare02 Spare01\n"
|
|
296
|
-
)
|
|
297
|
-
else:
|
|
298
|
-
msg = f"Unknown location, {location}"
|
|
299
|
-
SSX_LOGGER.error(msg)
|
|
300
|
-
raise ValueError(msg)
|
|
301
|
-
SSX_LOGGER.debug("Write headers done")
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
def run():
|
|
305
|
-
SSX_LOGGER.debug("Run Startup")
|
|
306
|
-
check_files("i24", [".addr", ".shot"])
|
|
307
|
-
SSX_LOGGER.info("Checked Files")
|
|
308
|
-
write_headers("i24", [".addr", ".shot"])
|
|
309
|
-
SSX_LOGGER.info("Written Headers")
|
|
310
|
-
SSX_LOGGER.info("Writing to Files has been disabled. Headers Only")
|
|
311
|
-
# Makes a file with random crystal positions
|
|
312
|
-
check_files("i24", ["rando.spec"])
|
|
313
|
-
write_headers("i24", ["rando.spec"])
|
|
314
|
-
SSX_LOGGER.debug("StartUp Done")
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
if __name__ == "__main__":
|
|
318
|
-
run()
|
|
@@ -3,7 +3,6 @@ Move on click gui for fixed targets at I24
|
|
|
3
3
|
Robin Owen 12 Jan 2021
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
import logging
|
|
7
6
|
from collections.abc import Sequence
|
|
8
7
|
|
|
9
8
|
import bluesky.plan_stubs as bps
|
|
@@ -17,10 +16,9 @@ from mx_bluesky.beamlines.i24.serial.fixed_target import (
|
|
|
17
16
|
i24ssx_Chip_Manager_py3v1 as manager,
|
|
18
17
|
)
|
|
19
18
|
from mx_bluesky.beamlines.i24.serial.fixed_target.ft_utils import Fiducials
|
|
19
|
+
from mx_bluesky.beamlines.i24.serial.log import SSX_LOGGER
|
|
20
20
|
from mx_bluesky.beamlines.i24.serial.parameters.constants import OAV1_CAM
|
|
21
21
|
|
|
22
|
-
logger = logging.getLogger("I24ssx.moveonclick")
|
|
23
|
-
|
|
24
22
|
|
|
25
23
|
def _get_beam_centre(oav: OAV):
|
|
26
24
|
"""Extract the beam centre x/y positions from the display.configuration file.
|
|
@@ -53,7 +51,7 @@ def _move_on_mouse_click_plan(
|
|
|
53
51
|
x, y = clicked_position
|
|
54
52
|
xmove = -1 * (beamX - x) * zoomcalibrator
|
|
55
53
|
ymove = 1 * (beamY - y) * zoomcalibrator
|
|
56
|
-
|
|
54
|
+
SSX_LOGGER.info(f"Moving X and Y {xmove} {ymove}")
|
|
57
55
|
xmovepmacstring = "#1J:" + str(xmove)
|
|
58
56
|
ymovepmacstring = "#2J:" + str(ymove)
|
|
59
57
|
yield from bps.abs_set(pmac.pmac_string, xmovepmacstring, wait=True)
|
|
@@ -66,7 +64,7 @@ def onMouse(event, x, y, flags, param):
|
|
|
66
64
|
RE = param[0]
|
|
67
65
|
pmac = param[1]
|
|
68
66
|
oav = param[2]
|
|
69
|
-
|
|
67
|
+
SSX_LOGGER.info(f"Clicked X and Y {x} {y}")
|
|
70
68
|
RE(_move_on_mouse_click_plan(oav, pmac, (x, y)))
|
|
71
69
|
|
|
72
70
|
|
|
@@ -159,7 +157,7 @@ def start_viewer(oav: OAV, pmac: PMAC, RE: RunEngine, oav1: str = OAV1_CAM):
|
|
|
159
157
|
cv.namedWindow("OAV1view")
|
|
160
158
|
cv.setMouseCallback("OAV1view", onMouse, param=[RE, pmac, oav]) # type: ignore
|
|
161
159
|
|
|
162
|
-
|
|
160
|
+
SSX_LOGGER.info("Showing camera feed. Press escape to close")
|
|
163
161
|
# Read captured video and store them in success and frame
|
|
164
162
|
success, frame = cap.read()
|
|
165
163
|
|
|
@@ -6,8 +6,8 @@ from os import environ
|
|
|
6
6
|
from pathlib import Path
|
|
7
7
|
|
|
8
8
|
import bluesky.plan_stubs as bps
|
|
9
|
-
from blueapi.core import MsgGenerator
|
|
10
9
|
from bluesky.log import logger as bluesky_logger
|
|
10
|
+
from bluesky.utils import MsgGenerator
|
|
11
11
|
from dodal.log import DEFAULT_GRAYLOG_PORT, ophyd_async_logger
|
|
12
12
|
from dodal.log import LOGGER as dodal_logger
|
|
13
13
|
|
|
@@ -41,7 +41,6 @@ PARAM_FILE_NAME = "parameters.json"
|
|
|
41
41
|
PARAM_FILE_PATH = _params_file_location()
|
|
42
42
|
PARAM_FILE_PATH_FT = PARAM_FILE_PATH / "fixed_target"
|
|
43
43
|
LITEMAP_PATH = PARAM_FILE_PATH_FT / "litemaps"
|
|
44
|
-
FULLMAP_PATH = PARAM_FILE_PATH_FT / "fullmaps"
|
|
45
44
|
# Paths for r only
|
|
46
45
|
PVAR_FILE_PATH = INTERNAL_FILES_PATH / "fixed_target/pvar_files"
|
|
47
46
|
CS_FILES_PATH = INTERNAL_FILES_PATH / "fixed_target/cs"
|
|
@@ -15,12 +15,13 @@ edm_path=$1
|
|
|
15
15
|
# Export env variable for the stages edm to work properly
|
|
16
16
|
export EDMDATAFILES="/dls_sw/prod/R3.14.12.3/support/motor/6-7-1dls14/motorApp/opi/edl"
|
|
17
17
|
|
|
18
|
+
# Get the directory of this script
|
|
19
|
+
current=$( realpath "$( dirname "$0" )" )
|
|
20
|
+
|
|
21
|
+
|
|
18
22
|
if [[ $NO_PROCESERV_TEST == true ]]; then
|
|
19
23
|
echo "Start the blueapi sever"
|
|
20
24
|
|
|
21
|
-
# Get the directory of this script
|
|
22
|
-
current=$( realpath "$( dirname "$0" )" )
|
|
23
|
-
|
|
24
25
|
# Run script to start blueapi serve
|
|
25
26
|
. $current/start_blueapi.sh
|
|
26
27
|
fi
|