allen_bradley_connect.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. import logging
  2. from pylogix import PLC
  3. from threading import Thread
  4. import time
  5. from datetime import datetime
  6. from structures.plant import *
  7. from structures.measurement import *
  8. from inputs.common import Input
  9. localtz = datetime.now().astimezone().tzinfo
  10. logger = logging.getLogger(__name__)
  11. class AllenBradleyCPU(Input):
  12. def __init__(self, host):
  13. super().__init__(self.read_handler)
  14. self.comm = PLC()
  15. self.comm.IPAddress = host
  16. self.interval = 0.02
  17. self.cpu_state_tags = {
  18. "ejector_move_down": "B14[31]",
  19. "ejector_move_up": "B14[32]",
  20. "carriage_move_out": "B14[34]",
  21. "carriage_move_in": "B14[35]",
  22. "side_clamps_open": "B14[37]",
  23. "side_clamps_close": "B14[38]",
  24. "table_move_down": "B14[42]",
  25. "table_move_up": "B14[43]",
  26. "gassing_platemove_out": "B14[45]",
  27. "gassing_plate_move_in": "B14[46]",
  28. "cope_eject_plate_move_out": "B14[48]",
  29. "cope_eject_plate_move_in": "B14[49]",
  30. "top_part_move_up": "B14[51]",
  31. "top_part_move_down": "B14[52]",
  32. "front_door_open": "B14[54]",
  33. "front_door_close": "B14[55]",
  34. "pneumatic_loose_part_1_move_out": "B14[57]",
  35. "pneumatic_loose_part_1_move_in": "B14[58]",
  36. "hydraulic_loose_part_2_move_out": "B14[60]",
  37. "hydraulic_loose_part_2_move_in": "B14[61]",
  38. "hydraulic_loose_part_3_move_out": "B14[63]",
  39. "hydraulic_loose_part_3_move_in": "B14[64]",
  40. "clamping_device_side_clamp_left_clamp": "B14[69]",
  41. "clamping_device_side_clamp_left_loose": "B14[70]",
  42. "clamping_device_side_clamp_right_clamp": "B14[72]",
  43. "clamping_device_side_clamp_right_loose": "B14[73]",
  44. "clamping_device_shoot_plate_clamp": "B14[81]",
  45. "clamping_device_shoot_plate_loose": "B14[82]",
  46. "sand_refill": "B14[83]",
  47. "sand_gate_close": "B14[84]",
  48. "sand_gate_open": "B14[85]",
  49. "shoot": "B14[93]",
  50. "clamping_device_gassing_plate_clamp": "B14[103]",
  51. "central_amine_supply_refill": "B16[12]",
  52. "gassing": "B16[13]",
  53. "gas_generator_process_coldbox_betaset": "B16[15]",
  54. "mixer_lid_move_up": "B18[31]",
  55. "mixer_lid_move_down": "B18[32]",
  56. "mixer_wing_motor_on": "B18[35]",
  57. "mixer_move_up": "B18[37]",
  58. "mixer_move_down": "B18[38]",
  59. "sand_dosing_unit_inlet": "B18[40]",
  60. "sand_dosing_unit_outlet": "B18[42]",
  61. "binder_1_sucking": "B18[44]",
  62. "binder_1_blowing": "B18[45]",
  63. "binder_2_suction": "B18[47]",
  64. "binder_2_blowing": "B18[48]",
  65. "binder_3_sucking": "B18[50]",
  66. "binder_3_blowing": "B18[51]",
  67. "binder_4_sucking": "B18[53]",
  68. "binder_4_blowing": "B18[54]",
  69. "additive_1_dosing": "B18[59]",
  70. "additive_2_dosing": "B18[60]",
  71. "mixer_bowl_direction_eject_1_machine": "B18[62]",
  72. "mixer_bowl_direction_eject_2_scrap": "B18[63]",
  73. "cleaning_cylinder_move_up": "B18[65]",
  74. "cleaning_cylinder_move_down": "B18[66]",
  75. "mixer_sand_slide_move_to_machine": "B18[68]",
  76. "mixer_sand_slide_move_to_scrap": "B18[69]",
  77. "vertical_mixersand_slide_gateclose": "B18[71]",
  78. "vertical_mixer_sand_slide_gate_open": "B18[72]",
  79. "sand_sender": "B18[73]",
  80. }
  81. self.measurement_tags = {
  82. "24V": "B200",
  83. "480V": "B201"
  84. }
  85. self.tags = list(self.cpu_state_tags.values()) + list(self.measurement_tags.values())
  86. def read_handler(self):
  87. timestamp = datetime.now(localtz)
  88. ret = self.comm.Read(self.tags)
  89. if ret[0].Status == "Success":
  90. cpu_values = {t: r.Value for t, r in zip(self.cpu_state_tags, ret)}
  91. self._q.put(CompactLogixState(timestamp, "AB", **cpu_values))
  92. offset = self.cpu_state_tags.values()
  93. ifm_values_count = 22
  94. data = [r.Value for r in ret[offset:offset+ifm_values_count]]
  95. channels = 16
  96. self._q.put(Measurement24v(timestamp, "AB",
  97. current = tuple([x / 10 for x in data[0:channels]]),
  98. status = tuple([data[16] & (1 << i) > 0 for i in range(channels)]),
  99. overload = tuple([data[17] & (1 << i) > 0 for i in range(channels)]),
  100. short_circuit = tuple([data[18] & (1 << i) > 0 for i in range(channels)]),
  101. limit = tuple([data[19] & (1 << i) > 0 for i in range(channels)]),
  102. pushbutton = tuple([data[20] & (1 << i) > 0 for i in range(channels)]),
  103. voltage = data[22] / 100
  104. ))
  105. offset += ifm_values_count
  106. data = [r.Value for r in ret[offset:offset+9]]
  107. self._q.put(Measurement480v(timestamp, "AB",
  108. voltage = tuple(data[0:3]),
  109. current = tuple(data[3:6]),
  110. phase = tuple(data[6:9])
  111. ))
  112. else:
  113. logger.error("CPU read: " + ret[0].Status)