Coverage for C:\Users\hjanssen\HOME\pyCharmProjects\ethz_hvl\hvl_ccb\hvl_ccb\dev\supercube\constants.py: 0%

# Coverage for C:\Users\hjanssen\HOME\pyCharmProjects\ethz_hvl\hvl_ccb\hvl_ccb\dev\supercube\constants.py : 0%

## 287 statements

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"""

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

5"""

6

7 from typing import cast, Sequence, Sized, Tuple

8

9 from aenum import IntEnum, EnumMeta

10

11 from hvl_ccb.utils.enum import ValueEnum, unique

12

13

14@unique

15 class 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)`!

25 class 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

37 class 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

131 class 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

152 class 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

170 T13_SOCKET_PORTS = (1, 2, 3)

171"""

172 Port numbers of SEV T13 power socket

173"""

174

175

176@unique

177 class 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

195 class 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

228 class 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

260 class 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

301 class _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

362 class _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

383 MeasurementsScaledInput = 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"""

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

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

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

395"""

396

397

398 MeasurementsDividerRatio = 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"""

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

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

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

410"""

411

412

413 class 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

434 class 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

443 class 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)`!

453 class 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

473 class 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

596 class 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

615 class _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

636 Alarms = 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"""

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

646"""

647

648

649 class 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

671 class 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

683 class _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

705 Door = 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"""

714 Variable NodeID strings for doors.

715"""

716

717 EarthingRod = 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"""

726 Variable NodeID strings for earthing rods.

727"""

728

729

730 class 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

795 class 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

807 class _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

828 MessageBoard = 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"""

837 Variable NodeID strings for message board lines.

838"""