Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# Copyright (c) 2019-2020 ETH Zurich, SIS ID and HVL D-ITET 

2# 

3""" 

4Constants, variable names for the Supercube OPC-connected devices. 

5""" 

6 

7from typing import cast, Sequence, Sized, Tuple 

8 

9from aenum import IntEnum, EnumMeta 

10 

11from hvl_ccb.utils.enum import ValueEnum, unique 

12 

13 

14@unique 

15class SupercubeOpcEndpoint(ValueEnum): 

16 """ 

17 OPC Server Endpoint strings for the supercube variants. 

18 """ 

19 

20 A = "Supercube Typ A" 

21 B = "Supercube Typ B" 

22 

23 

24# NOTE: super metaclass has to match metaclass of `super(GeneralSupport)`! 

25class GeneralSupportMeta(EnumMeta): 

26 def __new__(metacls, clsname, bases, clsdict, **kwargs): 

27 cls = EnumMeta.__new__( 

28 metacls, clsname, bases, clsdict, **kwargs 

29 ) 

30 # BEWARE: keep manually in sync with suffixes of enum instances; opt use dir() 

31 cls._port_range = range(1, 7) 

32 cls._contact_range = range(1, 3) 

33 return cls 

34 

35 

36@unique 

37class GeneralSupport(ValueEnum, metaclass=GeneralSupportMeta): 

38 """ 

39 NodeID strings for the support inputs and outputs. 

40 """ 

41 

42 in_1_1 = '"Ix_Allg_Support1_1"' 

43 in_1_2 = '"Ix_Allg_Support1_2"' 

44 in_2_1 = '"Ix_Allg_Support2_1"' 

45 in_2_2 = '"Ix_Allg_Support2_2"' 

46 in_3_1 = '"Ix_Allg_Support3_1"' 

47 in_3_2 = '"Ix_Allg_Support3_2"' 

48 in_4_1 = '"Ix_Allg_Support4_1"' 

49 in_4_2 = '"Ix_Allg_Support4_2"' 

50 in_5_1 = '"Ix_Allg_Support5_1"' 

51 in_5_2 = '"Ix_Allg_Support5_2"' 

52 in_6_1 = '"Ix_Allg_Support6_1"' 

53 in_6_2 = '"Ix_Allg_Support6_2"' 

54 out_1_1 = '"Qx_Allg_Support1_1"' 

55 out_1_2 = '"Qx_Allg_Support1_2"' 

56 out_2_1 = '"Qx_Allg_Support2_1"' 

57 out_2_2 = '"Qx_Allg_Support2_2"' 

58 out_3_1 = '"Qx_Allg_Support3_1"' 

59 out_3_2 = '"Qx_Allg_Support3_2"' 

60 out_4_1 = '"Qx_Allg_Support4_1"' 

61 out_4_2 = '"Qx_Allg_Support4_2"' 

62 out_5_1 = '"Qx_Allg_Support5_1"' 

63 out_5_2 = '"Qx_Allg_Support5_2"' 

64 out_6_1 = '"Qx_Allg_Support6_1"' 

65 out_6_2 = '"Qx_Allg_Support6_2"' 

66 

67 @classmethod 

68 def port_range(cls) -> Sequence[int]: 

69 """ 

70 Integer range of all ports. 

71 

72 :return: sequence of port numbers 

73 """ 

74 return cls._port_range 

75 

76 @classmethod 

77 def contact_range(cls) -> Sequence[int]: 

78 """ 

79 Integer range of all contacts. 

80 

81 :return: sequence of contact numbers 

82 """ 

83 return cls._contact_range 

84 

85 @classmethod 

86 def _validate_port_contact_numbers(cls, port: int, contact: int): 

87 """ 

88 Validate earthing stick number. 

89 

90 :param port: the port number 

91 :param contact: the contact number 

92 :raises ValueError: when port or contact number is not valid 

93 """ 

94 if port not in cls.port_range(): 

95 raise ValueError( 

96 f"Port number must be one of {list(cls.port_range())}" 

97 ) 

98 if contact not in cls.contact_range(): 

99 raise ValueError( 

100 f"Contact number must be one of {list(cls.contact_range())}" 

101 ) 

102 

103 @classmethod 

104 def output(cls, port: int, contact: int): 

105 """ 

106 Get the NodeID string for a support output. 

107 

108 :param port: the desired port (1..6) 

109 :param contact: the desired contact at the port (1..2) 

110 :return: the node id string 

111 :raises ValueError: when port or contact number is not valid 

112 """ 

113 cls._validate_port_contact_numbers(port, contact) 

114 return getattr(cls, "out_{}_{}".format(port, contact)) 

115 

116 @classmethod 

117 def input(cls, port: int, contact: int): 

118 """ 

119 Get the NodeID string for a support input. 

120 

121 :param port: the desired port (1..6) 

122 :param contact: the desired contact at the port (1..2) 

123 :return: the node id string 

124 :raises ValueError: when port or contact number is not valid 

125 """ 

126 cls._validate_port_contact_numbers(port, contact) 

127 return getattr(cls, "in_{}_{}".format(port, contact)) 

128 

129 

130@unique 

131class BreakdownDetection(ValueEnum): 

132 """ 

133 Node ID strings for the breakdown detection. 

134 

135 TODO: these variable NodeIDs are not tested and/or correct yet. 

136 """ 

137 

138 #: Boolean read-only variable indicating whether breakdown detection and fast 

139 #: switchoff is enabled in the system or not. 

140 activated = '"Ix_Allg_Breakdown_activated"' 

141 

142 #: Boolean read-only variable telling whether the fast switch-off has triggered. 

143 #: This can also be seen using the safety circuit state, therefore no method is 

144 #: implemented to read this out directly. 

145 triggered = '"Ix_Allg_Breakdown_triggered"' 

146 

147 #: Boolean writable variable to reset the fast switch-off. Toggle to re-enable. 

148 reset = '"Qx_Allg_Breakdown_reset"' 

149 

150 

151@unique 

152class GeneralSockets(ValueEnum): 

153 """ 

154 NodeID strings for the power sockets (3x T13 and 1xCEE16). 

155 """ 

156 

157 #: SEV T13 socket No. 1 (writable boolean). 

158 t13_1 = '"Qx_Allg_Socket_T13_1"' 

159 

160 #: SEV T13 socket No. 2 (writable boolean). 

161 t13_2 = '"Qx_Allg_Socket_T13_2"' 

162 

163 #: SEV T13 socket No. 3 (writable boolean). 

164 t13_3 = '"Qx_Allg_Socket_T13_3"' 

165 

166 #: CEE16 socket (writeable boolean). 

167 cee16 = '"Qx_Allg_Socket_CEE16"' 

168 

169 

170T13_SOCKET_PORTS = (1, 2, 3) 

171""" 

172Port numbers of SEV T13 power socket 

173""" 

174 

175 

176@unique 

177class Safety(ValueEnum): 

178 """ 

179 NodeID strings for the basic safety circuit status and green/red switches "ready" 

180 and "operate". 

181 """ 

182 

183 #: Status is a read-only integer containing the state number of the 

184 #: supercube-internal state machine. The values correspond to numbers in 

185 #: :class:`SafetyStatus`. 

186 status = '"DB_Safety_Circuit"."si_safe_status"' 

187 

188 #: Writable boolean for switching to Red Ready (locked, HV off) state. 

189 switch_to_ready = '"DB_Safety_Circuit"."sx_safe_switch_to_ready"' 

190 

191 #: Writable boolean for switching to Red Operate (locket, HV on) state. 

192 switch_to_operate = '"DB_Safety_Circuit"."sx_safe_switch_to_operate"' 

193 

194 

195class SafetyStatus(IntEnum): 

196 """ 

197 Safety status values that are possible states returned from 

198 :meth:`hvl_ccb.dev.supercube.base.Supercube.get_status`. These 

199 values correspond to the states of the Supercube's safety circuit statemachine. 

200 """ 

201 

202 #: System is initializing or booting. 

203 Initializing = 0 

204 

205 #: System is safe, lamps are green and some safety elements are not in place such 

206 #: that it cannot be switched to red currently. 

207 GreenNotReady = 1 

208 

209 #: System is safe and all safety elements are in place to be able to switch to 

210 #: *ready*. 

211 GreenReady = 2 

212 

213 #: System is locked in red state and *ready* to go to *operate* mode. 

214 RedReady = 3 

215 

216 #: System is locked in red state and in *operate* mode, i.e. high voltage on. 

217 RedOperate = 4 

218 

219 #: Fast turn off triggered and switched off the system. Reset FSO to go back to a 

220 #: normal state. 

221 QuickStop = 5 

222 

223 #: System is in error mode. 

224 Error = 6 

225 

226 

227@unique 

228class Power(ValueEnum): 

229 """ 

230 Variable NodeID strings concerning power data. 

231 

232 TODO: these variable NodeIDs are not tested and/or correct yet, they don't exist 

233 yet on Supercube side. 

234 """ 

235 

236 #: Primary voltage in volts, measured by the frequency converter at its output. 

237 #: (read-only) 

238 voltage_primary = "Qr_Power_FU_actual_Voltage" 

239 

240 #: Primary current in ampere, measured by the frequency converter. (read-only) 

241 current_primary = "Qr_Power_FU_actual_Current" 

242 

243 #: Power setup that is configured using the Supercube HMI. The value corresponds to 

244 #: the ones in :class:`PowerSetup`. (read-only) 

245 setup = "Qi_Power_Setup" 

246 

247 #: Voltage slope in V/s. 

248 voltage_slope = "Ir_Power_dUdt" 

249 

250 #: Target voltage setpoint in V. 

251 voltage_target = "Ir_Power_Target_Voltage" 

252 

253 #: Maximum voltage allowed by the current experimental setup. (read-only) 

254 voltage_max = "Iw_Power_max_Voltage" 

255 

256 #: Frequency converter output frequency. (read-only) 

257 frequency = "Ir_Power_FU_Frequency" 

258 

259 

260class PowerSetup(IntEnum): 

261 """ 

262 Possible power setups corresponding to the value of variable :attr:`Power.setup`. 

263 """ 

264 

265 #: No safety switches, use only safety components (doors, fence, earthing...) 

266 #: without any power. 

267 NoPower = 0 

268 

269 #: External power supply fed through blue CEE32 input using isolation transformer 

270 #: and safety switches of the Supercube, or using an external safety switch 

271 #: attached to the Supercube Type B. 

272 External = 1 

273 

274 #: AC voltage with MWB transformer set to 50kV maximum voltage. 

275 AC_SingleStage_50kV = 2 

276 

277 #: AC voltage with MWB transformer set to 100kV maximum voltage. 

278 AC_SingleStage_100kV = 3 

279 

280 #: AC voltage with two MWB transformers, one at 100kV and the other at 50kV, 

281 #: resulting in a total maximum voltage of 150kV. 

282 AC_DoubleStage_150kV = 4 

283 

284 #: AC voltage with two MWB transformers both at 100kV, resulting in a total 

285 #: maximum voltage of 200kV 

286 AC_DoubleStage_200kV = 5 

287 

288 #: Internal usage of the frequency converter, controlling to the primary voltage 

289 #: output of the supercube itself (no measurement transformer used) 

290 Internal = 6 

291 

292 #: DC voltage with one AC transformer set to 100kV AC, resulting in 140kV DC 

293 DC_SingleStage_140kV = 7 

294 

295 #: DC voltage with two AC transformers set to 100kV AC each, resulting in 280kV 

296 #: DC in total (or a single stage transformer with Greinacher voltage doubling 

297 #: rectifier) 

298 DC_DoubleStage_280kV = 8 

299 

300 

301class _PrefixedNumbersEnumBase(ValueEnum): 

302 """ 

303 Base class for enums with "{prefix}{n}" instance names, where n=1..N. 

304 """ 

305 

306 @classmethod 

307 def range(cls) -> Sequence[int]: 

308 """ 

309 Integer range of all channels. 

310 

311 :return: sequence of channel numbers 

312 """ 

313 return range(1, len(cast(Sized, cls))+1) 

314 

315 @classmethod 

316 def _validate_number(cls, number: int): 

317 """ 

318 Validate enum instance number. 

319 

320 :param number: the enum instance number (1..N) 

321 :raises ValueError: when enum instance number is not in 1..N range 

322 """ 

323 if number not in cls.range(): 

324 raise ValueError( 

325 f"{cls._prefix()} number must be one of {list(cls.range())}" 

326 ) 

327 

328 @classmethod 

329 def _prefix(cls) -> str: 

330 """ 

331 Enum instances name prefix: "{prefix}{n}" 

332 

333 :return: enum instances prefix string 

334 """ 

335 raise NotImplementedError("Implement in subclass") 

336 

337 @property 

338 def number(self) -> int: 

339 """ 

340 Get corresponding enum instance number. 

341 

342 :return: enum instance number (1..N) 

343 """ 

344 # Py >=3.9: self.name.removeprefix() 

345 return int(self.name[len(self._prefix()):]) 

346 

347 # no type return as it would be a arguably too complex/obscure; 

348 # cf. https://github.com/python/typing/issues/58#issuecomment-326240794 

349 @classmethod 

350 def get(cls, number: int): 

351 """ 

352 Get the enum instance for a given number. 

353 

354 :param number: the instance number (1..N) 

355 :return: the enum instance for the given number. 

356 :raises ValueError: when instance number is not in the 1..N range 

357 """ 

358 cls._validate_number(number) 

359 return getattr(cls, f"{cls._prefix()}{number}") 

360 

361 

362class _InputEnumBase(_PrefixedNumbersEnumBase): 

363 """ 

364 Base class for enums with "input_{n}" instance names, where n=1..N. 

365 """ 

366 

367 @classmethod 

368 def _prefix(cls) -> str: 

369 return "input_" 

370 

371 @classmethod 

372 def input(cls, channel: int): 

373 """ 

374 Get the enum instance for a given channel number. 

375 

376 :param channel: the channel number (1..N) 

377 :return: the enum instance for the given channel. 

378 :raises ValueError: when channel number is not in the 1..N range 

379 """ 

380 return cls.get(channel) 

381 

382 

383MeasurementsScaledInput = unique(_InputEnumBase( 

384 "MeasurementsScaledInput", 

385 { 

386 f"{_InputEnumBase._prefix()}{n}": 

387 f'"DB_Measurements"."si_scaled_Voltage_Input_{n}"' 

388 for n in range(1, 5) 

389 } 

390)) 

391""" 

392Variable NodeID strings for the four analog BNC inputs for measuring voltage. 

393The voltage returned in these variables is already scaled with the set ratio, 

394which can be read using the variables in :class:`MeasurementsDividerRatio`. 

395""" 

396 

397 

398MeasurementsDividerRatio = unique(_InputEnumBase( 

399 "MeasurementsDividerRatio", 

400 { 

401 f"{_InputEnumBase._prefix()}{n}": 

402 f'"DB_Measurements"."si_Divider_Ratio_{n}"' 

403 for n in range(1, 5) 

404 } 

405)) 

406""" 

407Variable NodeID strings for the measurement input scaling ratios. These ratios 

408are defined in the Supercube HMI setup and are provided in the python module here 

409to be able to read them out, allowing further calculations. 

410""" 

411 

412 

413class EarthingStickStatus(IntEnum): 

414 """ 

415 Status of an earthing stick. These are the possible values in the status integer 

416 e.g. in :attr:`EarthingStick.status_1`. 

417 """ 

418 

419 #: Earthing stick is deselected and not enabled in safety circuit. To get out of 

420 #: this state, the earthing has to be enabled in the Supercube HMI setup. 

421 inactive = 0 

422 

423 #: Earthing is closed (safe). 

424 closed = 1 

425 

426 #: Earthing is open (not safe). 

427 open = 2 

428 

429 #: Earthing is in error, e.g. when the stick did not close correctly or could not 

430 #: open. 

431 error = 3 

432 

433 

434class EarthingStickOperatingStatus(IntEnum): 

435 """ 

436 Operating Status for an earthing stick. Stick can be used in auto or manual mode. 

437 """ 

438 

439 auto = 0 

440 manual = 1 

441 

442 

443class EarthingStickOperation(IntEnum): 

444 """ 

445 Operation of the earthing stick in manual operating mode. Can be closed of opened. 

446 """ 

447 

448 open = 0 

449 close = 1 

450 

451 

452# NOTE: super metaclass has to match metaclass of `super(EarthingStick)`! 

453class EarthingStickMeta(EnumMeta): 

454 def __new__(metacls, clsname, bases, clsdict, **kwargs): 

455 cls = EnumMeta.__new__( 

456 metacls, clsname, bases, clsdict, **kwargs 

457 ) 

458 # BEWARE: keep manually in sync with suffixes of enum instances; opt use dir() 

459 cls._range = range(1, 7) 

460 cls._statuses = tuple( 

461 getattr(cls, f"status_{number}") for number in cls._range 

462 ) 

463 cls._manuals = tuple( 

464 getattr(cls, f"manual_{number}") for number in cls._range 

465 ) 

466 cls._operating_statuses = tuple( 

467 getattr(cls, f"operating_status_{number}") for number in cls._range 

468 ) 

469 return cls 

470 

471 

472@unique 

473class EarthingStick(ValueEnum, metaclass=EarthingStickMeta): 

474 """ 

475 Variable NodeID strings for all earthing stick statuses (read-only integer) and 

476 writable booleans for setting the earthing in manual mode. 

477 """ 

478 

479 status_1 = '"DB_Safety_Circuit"."Earthstick_1"."si_HMI_Status"' 

480 status_2 = '"DB_Safety_Circuit"."Earthstick_2"."si_HMI_Status"' 

481 status_3 = '"DB_Safety_Circuit"."Earthstick_3"."si_HMI_Status"' 

482 status_4 = '"DB_Safety_Circuit"."Earthstick_4"."si_HMI_Status"' 

483 status_5 = '"DB_Safety_Circuit"."Earthstick_5"."si_HMI_Status"' 

484 status_6 = '"DB_Safety_Circuit"."Earthstick_6"."si_HMI_Status"' 

485 

486 manual_1 = '"DB_Safety_Circuit"."Earthstick_1"."sx_earthing_manually"' 

487 manual_2 = '"DB_Safety_Circuit"."Earthstick_2"."sx_earthing_manually"' 

488 manual_3 = '"DB_Safety_Circuit"."Earthstick_3"."sx_earthing_manually"' 

489 manual_4 = '"DB_Safety_Circuit"."Earthstick_4"."sx_earthing_manually"' 

490 manual_5 = '"DB_Safety_Circuit"."Earthstick_5"."sx_earthing_manually"' 

491 manual_6 = '"DB_Safety_Circuit"."Earthstick_6"."sx_earthing_manually"' 

492 

493 operating_status_1 = '"DB_Safety_Circuit"."Earthstick_1"."sx_manual_control_active"' 

494 operating_status_2 = '"DB_Safety_Circuit"."Earthstick_2"."sx_manual_control_active"' 

495 operating_status_3 = '"DB_Safety_Circuit"."Earthstick_3"."sx_manual_control_active"' 

496 operating_status_4 = '"DB_Safety_Circuit"."Earthstick_4"."sx_manual_control_active"' 

497 operating_status_5 = '"DB_Safety_Circuit"."Earthstick_5"."sx_manual_control_active"' 

498 operating_status_6 = '"DB_Safety_Circuit"."Earthstick_6"."sx_manual_control_active"' 

499 

500 @property 

501 def number(self) -> int: 

502 """ 

503 Get corresponding earthing stick number. 

504 

505 :return: earthing stick number (1..6) 

506 """ 

507 return int(self.name.rpartition("_")[-1]) 

508 

509 @classmethod 

510 def range(cls) -> Sequence[int]: 

511 """ 

512 Integer range of all earthing sticks. 

513 

514 :return: sequence of earthing sticks numbers 

515 """ 

516 return cls._range 

517 

518 @classmethod 

519 def _validate_earthing_stick_number(cls, number: int): 

520 """ 

521 Validate earthing stick number. 

522 

523 :param number: the earthing stick number 

524 :raises ValueError: when earthing stick number is not valid 

525 """ 

526 if number not in cls.range(): 

527 raise ValueError( 

528 f"Earthing stick number must be one of {list(cls.range())}" 

529 ) 

530 

531 @classmethod 

532 def statuses(cls) -> Tuple["EarthingStick", ...]: 

533 """ 

534 Get all earthing stick status instances. 

535 

536 :return: tuple of status instances 

537 """ 

538 return cls._statuses 

539 

540 @classmethod 

541 def status(cls, number: int) -> "EarthingStick": 

542 """ 

543 Get the status enum instance for an earthing stick number. 

544 

545 :param number: the earthing stick (1..6) 

546 :return: the status instance 

547 :raises ValueError: when earthing stick number is not valid 

548 """ 

549 cls._validate_earthing_stick_number(number) 

550 return cls.statuses()[number-1] 

551 

552 @classmethod 

553 def manuals(cls) -> Tuple["EarthingStick", ...]: 

554 """ 

555 Get all earthing stick manual instances. 

556 

557 :return: tuple of manual instances 

558 """ 

559 return cls._manuals 

560 

561 @classmethod 

562 def manual(cls, number: int): 

563 """ 

564 Get the manual enum instance for an earthing stick number. 

565 

566 :param number: the earthing stick (1..6) 

567 :return: the manual instance 

568 :raises ValueError: when earthing stick number is not valid 

569 """ 

570 cls._validate_earthing_stick_number(number) 

571 return cls.manuals()[number-1] 

572 

573 @classmethod 

574 def operating_statuses(cls) -> Tuple["EarthingStick", ...]: 

575 """ 

576 Get all earthing stick operating status instances. 

577 

578 :return: tuple of operating status instances 

579 """ 

580 return cls._operating_statuses 

581 

582 @classmethod 

583 def operating_status(cls, number: int): 

584 """ 

585 Get the operating status enum instance for an earthing stick number. 

586 

587 :param number: the earthing stick (1..6) 

588 :return: the operating status instance 

589 :raises ValueError: when earthing stick number is not valid 

590 """ 

591 cls._validate_earthing_stick_number(number) 

592 return cls.operating_statuses()[number-1] 

593 

594 

595@unique 

596class Errors(ValueEnum): 

597 """ 

598 Variable NodeID strings for information regarding error, warning and message 

599 handling. 

600 """ 

601 

602 #: Boolean read-only variable telling if a message is active. 

603 message = '"DB_Message_Buffer"."Info_active"' 

604 

605 #: Boolean read-only variable telling if a warning is active. 

606 warning = '"DB_Message_Buffer"."Warning_active"' 

607 

608 #: Boolean read-only variable telling if a stop is active. 

609 stop = '"DB_Message_Buffer"."Stop_active"' 

610 

611 #: Writable boolean for the error quit button. 

612 quit = '"DB_Message_Buffer"."Reset_button"' 

613 

614 

615class _AlarmEnumBase(_PrefixedNumbersEnumBase): 

616 """ 

617 Base class for enums with "Alarm{n}" instance names, where n=1..N. 

618 """ 

619 

620 @classmethod 

621 def _prefix(cls) -> str: 

622 return "Alarm" 

623 

624 @classmethod 

625 def Alarm(cls, number: int): 

626 """ 

627 Get the enum instance for a given alarm number. 

628 

629 :param number: the alarm number (1..N) 

630 :return: the enum instance for the alarm number. 

631 :raises ValueError: when alarm number is not in the 1..N range 

632 """ 

633 return cls.get(number) 

634 

635 

636Alarms = unique(_AlarmEnumBase( 

637 "Alarms", 

638 { 

639 f"Alarm{n}": 

640 f'"DB_Alarm_HMI"."Alarm{n}"' 

641 for n in range(1, 152) 

642 }, 

643)) 

644""" 

645Alarms enumeration containing all variable NodeID strings for the alarm array. 

646""" 

647 

648 

649class DoorStatus(IntEnum): 

650 """ 

651 Possible status values for doors. 

652 """ 

653 

654 #: not enabled in Supercube HMI setup, this door is not supervised. 

655 inactive = 0 

656 

657 #: Door is open. 

658 open = 1 

659 

660 #: Door is closed, but not locked. 

661 closed = 2 

662 

663 #: Door is closed and locked (safe state). 

664 locked = 3 

665 

666 #: Door has an error or was opened in locked state (either with emergency stop or 

667 #: from the inside). 

668 error = 4 

669 

670 

671class EarthingRodStatus(IntEnum): 

672 """ 

673 Possible status values for earthing rods. 

674 """ 

675 #: earthing rod is somewhere in the experiment 

676 #: and blocks the start of the experiment 

677 experiment_blocked = 0 

678 

679 #: earthing rod is hanging next to the door, experiment is ready to operate 

680 experiment_ready = 1 

681 

682 

683class _DoorEnumBase(_PrefixedNumbersEnumBase): 

684 """ 

685 Base class for enums with "status_{n}" instance names, where n=1..N is the door 

686 number. 

687 """ 

688 

689 @classmethod 

690 def _prefix(cls) -> str: 

691 return "status_" 

692 

693 @classmethod 

694 def status(cls, door: int): 

695 """ 

696 Get the enum instance for a given door number. 

697 

698 :param number: the door number (1..N) 

699 :return: the enum instance for the given door number. 

700 :raises ValueError: when door number is not in the 1..N range 

701 """ 

702 return cls.get(door) 

703 

704 

705Door = unique(_DoorEnumBase( 

706 "Door", 

707 { 

708 f"{_DoorEnumBase._prefix()}{n}": 

709 f'"DB_Safety_Circuit"."Door_{n}"."si_HMI_status"' 

710 for n in range(1, 4) 

711 } 

712)) 

713""" 

714Variable NodeID strings for doors. 

715""" 

716 

717EarthingRod = unique(_DoorEnumBase( 

718 "EarthingRod", 

719 { 

720 f"{_DoorEnumBase._prefix()}{n}": 

721 f'"DB_Safety_Circuit"."Door_{n}"."Ix_earthingrod"' 

722 for n in range(1, 4) 

723 } 

724)) 

725""" 

726Variable NodeID strings for earthing rods. 

727""" 

728 

729 

730class AlarmText(ValueEnum): 

731 """ 

732 This enumeration contains textual representations for all error classes (stop, 

733 warning and message) of the Supercube system. Use the :meth:`AlarmText.get` 

734 method to retrieve the enum of an alarm number. 

735 """ 

736 

737 # Safety elements 

738 Alarm1 = "STOP Emergency Stop 1" 

739 Alarm2 = "STOP Emergency Stop 2" 

740 Alarm3 = "STOP Emergency Stop 3" 

741 Alarm4 = "STOP Safety Switch 1 error" 

742 Alarm5 = "STOP Safety Switch 2 error" 

743 Alarm6 = "STOP Door 1 lock supervision" 

744 Alarm7 = "STOP Door 2 lock supervision" 

745 Alarm8 = "STOP Door 3 lock supervision" 

746 Alarm9 = "STOP Earthing stick 1 error while opening" 

747 Alarm10 = "STOP Earthing stick 2 error while opening" 

748 Alarm11 = "STOP Earthing stick 3 error while opening" 

749 Alarm12 = "STOP Earthing stick 4 error while opening" 

750 Alarm13 = "STOP Earthing stick 5 error while opening" 

751 Alarm14 = "STOP Earthing stick 6 error while opening" 

752 Alarm15 = "STOP Earthing stick 1 error while closing" 

753 Alarm16 = "STOP Earthing stick 2 error while closing" 

754 Alarm17 = "STOP Earthing stick 3 error while closing" 

755 Alarm18 = "STOP Earthing stick 4 error while closing" 

756 Alarm19 = "STOP Earthing stick 5 error while closing" 

757 Alarm20 = "STOP Earthing stick 6 error while closing" 

758 Alarm21 = "STOP Safety fence 1" 

759 Alarm22 = "STOP Safety fence 2" 

760 Alarm23 = "STOP OPC connection error" 

761 Alarm24 = "STOP Grid power failure" 

762 Alarm25 = "STOP UPS failure" 

763 Alarm26 = "STOP 24V PSU failure" 

764 

765 # Doors 

766 Alarm41 = "WARNING Door 1: Use earthing rod!" 

767 Alarm42 = "MESSAGE Door 1: Earthing rod is still in setup." 

768 Alarm43 = "WARNING Door 2: Use earthing rod!" 

769 Alarm44 = "MESSAGE Door 2: Earthing rod is still in setup." 

770 Alarm45 = "WARNING Door 3: Use earthing rod!" 

771 Alarm46 = "MESSAGE Door 3: Earthing rod is still in setup." 

772 

773 # General 

774 Alarm47 = "MESSAGE UPS charge < 85%" 

775 Alarm48 = "MESSAGE UPS running on battery" 

776 

777 # generic not defined alarm text 

778 not_defined = "NO ALARM TEXT DEFINED" 

779 

780 @classmethod 

781 def get(cls, alarm: int): 

782 """ 

783 Get the attribute of this enum for an alarm number. 

784 

785 :param alarm: the alarm number 

786 :return: the enum for the desired alarm number 

787 """ 

788 

789 try: 

790 return getattr(cls, "Alarm{}".format(alarm)) 

791 except AttributeError: 

792 return cls.not_defined 

793 

794 

795class OpcControl(ValueEnum): 

796 """ 

797 Variable NodeID strings for supervision of the OPC connection from the 

798 controlling workstation to the Supercube. 

799 """ 

800 

801 #: writable boolean to enable OPC remote control and display a message window on 

802 #: the Supercube HMI. 

803 active = '"DB_OPC_Connection"."sx_OPC_active"' 

804 live = '"DB_OPC_Connection"."sx_OPC_lifebit"' 

805 

806 

807class _LineEnumBase(_PrefixedNumbersEnumBase): 

808 """ 

809 Base class for enums with "input_{n}" instance names, where n=1..N. 

810 """ 

811 

812 @classmethod 

813 def _prefix(cls) -> str: 

814 return "line_" 

815 

816 @classmethod 

817 def line(cls, number: int): 

818 """ 

819 Get the enum instance for a given line number. 

820 

821 :param number: the line number (1..M) 

822 :return: the enum instance for the given line number. 

823 :raises ValueError: when line number is not in the 1..N range 

824 """ 

825 return cls.get(number) 

826 

827 

828MessageBoard = unique(_LineEnumBase( 

829 "MessageBoard", 

830 { 

831 f"{_LineEnumBase._prefix()}{n}": 

832 f'"DB_OPC_Connection"."Is_status_Line_{n}"' 

833 for n in range(1, 16) 

834 } 

835)) 

836""" 

837Variable NodeID strings for message board lines. 

838"""