Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.
 
 
 
 
 
 

153 lignes
5.6 KiB

  1. import unittest
  2. from modbus_rtu import build_read_holding, build_write_multiple, build_write_single, valid_crc
  3. from plsr_protocol import (
  4. PULSE_POINTS,
  5. SECONDARY_POINTS,
  6. Command,
  7. DirectionLogic,
  8. Register,
  9. SendMode,
  10. STATUS_REGISTER_COUNT,
  11. WaitCondition,
  12. calculate_execution_total,
  13. join_i32,
  14. join_u32,
  15. parse_status,
  16. segment_base,
  17. signed_to_u32,
  18. split_u32,
  19. register_read_count,
  20. )
  21. class ParameterTable2026Tests(unittest.TestCase):
  22. def test_low_word_is_at_low_address(self):
  23. self.assertEqual(split_u32(0x12345678), [0x5678, 0x1234])
  24. self.assertEqual(join_u32(0x5678, 0x1234), 0x12345678)
  25. self.assertEqual(join_i32(0xFF9C, 0xFFFF), -100)
  26. def test_system_and_status_addresses(self):
  27. self.assertEqual(int(Register.PULSE_POINT), 0x1000)
  28. self.assertEqual(int(Register.MAX_FREQ_HI), 0x1015)
  29. self.assertEqual(register_read_count(), 0x16)
  30. self.assertEqual(int(Register.CUMULATIVE_POSITION_LO), 0x2000)
  31. self.assertEqual(int(Register.CONTROL), 0x3000)
  32. def test_segment_stride(self):
  33. self.assertEqual(segment_base(0), 0x1100)
  34. self.assertEqual(segment_base(9), 0x1190)
  35. def test_start_control_frame(self):
  36. frame = build_write_single(1, int(Register.CONTROL), int(Command.START))
  37. self.assertTrue(valid_crc(frame))
  38. self.assertEqual(frame[:6], bytes.fromhex("01 06 30 00 00 01"))
  39. def test_segment_frame_layout(self):
  40. values = split_u32(1000) + split_u32((-200) & 0xFFFFFFFF)
  41. values += [int(WaitCondition.WAIT_TIME), 500, 0, 2]
  42. frame = build_write_multiple(1, segment_base(0), values)
  43. self.assertTrue(valid_crc(frame))
  44. self.assertEqual(frame[2:7], bytes.fromhex("11 00 00 08 10"))
  45. def test_status_read_frame(self):
  46. frame = build_read_holding(
  47. 1, int(Register.CUMULATIVE_POSITION_LO), STATUS_REGISTER_COUNT
  48. )
  49. self.assertTrue(valid_crc(frame))
  50. self.assertEqual(frame[:6], bytes.fromhex("01 03 20 00 00 1B"))
  51. def test_status_pulse_counts(self):
  52. status = parse_status([30, 0, 0, 0, 2, 0, 0, 10, 0, 30, 0])
  53. self.assertEqual(status["current_pulses"], 10)
  54. self.assertEqual(status["total_pulses"], 30)
  55. def test_diagnostic_status_values(self):
  56. registers = [0] * STATUS_REGISTER_COUNT
  57. registers[11] = 0x001E
  58. registers[12] = 2
  59. registers[13] = 3
  60. registers[14:16] = split_u32(1000)
  61. registers[16:18] = split_u32(1000)
  62. registers[18:20] = split_u32(5000)
  63. registers[20:22] = split_u32(4998)
  64. registers[22:24] = split_u32(2)
  65. status = parse_status(registers)
  66. self.assertEqual(status["diagnostic_expected_pulses"], 1000)
  67. self.assertEqual(status["diagnostic_observed_pulses"], 1000)
  68. self.assertEqual(status["diagnostic_actual_frequency"], 4998)
  69. self.assertEqual(status["diagnostic_max_frequency_error"], 2)
  70. def test_ab_reverse_segment_uses_signed_pulse_count(self):
  71. self.assertEqual(split_u32(signed_to_u32(-100)), [0xFF9C, 0xFFFF])
  72. def test_b_phase_point_encoding(self):
  73. self.assertEqual(SECONDARY_POINTS[0].split()[0], "Y12")
  74. self.assertEqual(SECONDARY_POINTS[3].split()[0], "Y15")
  75. def test_output_mode_register(self):
  76. self.assertEqual(int(Register.OUTPUT_MODE), 0x100F)
  77. def test_send_mode_register_values(self):
  78. self.assertEqual(int(Register.SEND_MODE), 0x1004)
  79. self.assertEqual(int(SendMode.COMPLETE), 0)
  80. self.assertEqual(int(SendMode.FOLLOW), 1)
  81. def test_direction_logic_register_values(self):
  82. self.assertEqual(int(Register.DIRECTION_LOGIC), 0x1006)
  83. self.assertEqual(int(DirectionLogic.POSITIVE), 0)
  84. self.assertEqual(int(DirectionLogic.NEGATIVE), 1)
  85. def test_y3_uses_pf9_tim14(self):
  86. self.assertEqual(PULSE_POINTS[3], "Y3 / PF9 / TIM14_CH1")
  87. def test_execution_total_starts_from_selected_segment(self):
  88. segments = [
  89. (100, 1000, 0),
  90. (200, 1000, 0),
  91. (-300, 1000, 0),
  92. ]
  93. self.assertEqual(calculate_execution_total(segments, 2), (500, False))
  94. def test_execution_total_follows_jump_and_detects_cycle(self):
  95. segments = [
  96. (100, 1000, 3),
  97. (200, 1000, 0),
  98. (300, 1000, 1),
  99. ]
  100. self.assertEqual(calculate_execution_total(segments, 1), (400, True))
  101. def test_clear_total_control_frame(self):
  102. frame = build_write_single(
  103. 1, int(Register.CONTROL), int(Command.CLEAR_TOTAL)
  104. )
  105. self.assertTrue(valid_crc(frame))
  106. self.assertEqual(frame[:6], bytes.fromhex("01 06 30 00 00 08"))
  107. def test_save_outputs_control_frame(self):
  108. frame = build_write_single(
  109. 1, int(Register.CONTROL), int(Command.SAVE_OUTPUTS)
  110. )
  111. self.assertTrue(valid_crc(frame))
  112. self.assertEqual(frame[:6], bytes.fromhex("01 06 30 00 00 10"))
  113. def test_clear_diagnostic_control_frame(self):
  114. frame = build_write_single(
  115. 1, int(Register.CONTROL), int(Command.CLEAR_DIAGNOSTIC)
  116. )
  117. self.assertTrue(valid_crc(frame))
  118. self.assertEqual(frame[:6], bytes.fromhex("01 06 30 00 00 20"))
  119. def test_runtime_frequency_is_separate_from_default_speed(self):
  120. self.assertEqual(int(Register.TARGET_FREQ_LO), 0x100B)
  121. self.assertEqual(int(Register.RUNTIME_FREQ_LO), 0x1016)
  122. frame = build_write_single(
  123. 1, int(Register.CONTROL), int(Command.UPDATE_FREQUENCY)
  124. )
  125. self.assertTrue(valid_crc(frame))
  126. self.assertEqual(frame[:6], bytes.fromhex("01 06 30 00 00 40"))
  127. if __name__ == "__main__":
  128. unittest.main()