Нема описа

test_charge_point.py 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. from dataclasses import asdict
  2. import pytest
  3. from ocpp.charge_point import camel_to_snake_case, remove_nones, snake_to_camel_case
  4. from ocpp.routing import create_route_map, on
  5. from ocpp.v16.call import (
  6. BootNotificationPayload,
  7. GetConfigurationPayload,
  8. MeterValuesPayload,
  9. )
  10. from ocpp.v16.datatypes import MeterValue, SampledValue
  11. from ocpp.v16.enums import Action
  12. from ocpp.v20 import ChargePoint as cp
  13. from ocpp.v201.call import SetNetworkProfilePayload
  14. from ocpp.v201.datatypes import NetworkConnectionProfileType
  15. from ocpp.v201.enums import OCPPInterfaceType, OCPPTransportType, OCPPVersionType
  16. def test_getters_should_not_be_called_during_routemap_setup():
  17. class ChargePoint(cp):
  18. @property
  19. def foo(self):
  20. raise RuntimeError("this will be raised")
  21. try:
  22. ChargePoint("blah", None)
  23. except RuntimeError as e:
  24. assert str(e) == "this will be raised"
  25. pytest.fail("Getter was called during ChargePoint creation")
  26. def test_multiple_classes_with_same_name_for_handler():
  27. class ChargerA(cp):
  28. @on(Action.Heartbeat)
  29. def heartbeat(self, **kwargs):
  30. pass
  31. class ChargerB(cp):
  32. @on(Action.Heartbeat)
  33. def heartbeat(self, **kwargs):
  34. pass
  35. A = ChargerA("A", None)
  36. B = ChargerB("B", None)
  37. route_mapA = create_route_map(A)
  38. route_mapB = create_route_map(B)
  39. assert route_mapA["Heartbeat"] != route_mapB["Heartbeat"]
  40. @pytest.mark.parametrize(
  41. "test_input,expected",
  42. [
  43. ({"transactionId": "74563478"}, {"transaction_id": "74563478"}),
  44. ({"fullSoC": 100}, {"full_soc": 100}),
  45. ],
  46. )
  47. def test_camel_to_snake_case(test_input, expected):
  48. result = camel_to_snake_case(test_input)
  49. assert result == expected
  50. @pytest.mark.parametrize(
  51. "test_input,expected",
  52. [
  53. ({"transaction_id": "74563478"}, {"transactionId": "74563478"}),
  54. ({"full_soc": 100}, {"fullSoC": 100}),
  55. ({"ev_min_v2x_energy_request": 200}, {"evMinV2XEnergyRequest": 200}),
  56. ({"v2x_charging_ctrlr": 200}, {"v2xChargingCtrlr": 200}),
  57. ],
  58. )
  59. def test_snake_to_camel_case(test_input, expected):
  60. result = snake_to_camel_case(test_input)
  61. assert result == expected
  62. def test_remove_nones():
  63. expected_payload = {"charge_point_model": "foo", "charge_point_vendor": "bar"}
  64. payload = BootNotificationPayload(
  65. charge_point_model="foo",
  66. charge_point_vendor="bar",
  67. charge_box_serial_number=None,
  68. )
  69. payload = asdict(payload)
  70. assert expected_payload == remove_nones(payload)
  71. def test_nested_remove_nones():
  72. expected_payload = {
  73. "configuration_slot": 1,
  74. "connection_data": {
  75. "ocpp_version": "OCPP20",
  76. "ocpp_transport": "JSON",
  77. "ocpp_csms_url": "wss://localhost:9000",
  78. "message_timeout": 60,
  79. "security_profile": 1,
  80. "ocpp_interface": "Wired0",
  81. },
  82. }
  83. connection_data = NetworkConnectionProfileType(
  84. ocpp_version=OCPPVersionType.ocpp20,
  85. ocpp_transport=OCPPTransportType.json,
  86. ocpp_csms_url="wss://localhost:9000",
  87. message_timeout=60,
  88. security_profile=1,
  89. ocpp_interface=OCPPInterfaceType.wired0,
  90. vpn=None,
  91. apn=None,
  92. )
  93. payload = SetNetworkProfilePayload(
  94. configuration_slot=1, connection_data=connection_data
  95. )
  96. payload = asdict(payload)
  97. assert expected_payload == remove_nones(payload)
  98. def test_nested_list_remove_nones():
  99. expected_payload = {
  100. "connector_id": 3,
  101. "meter_value": [
  102. {
  103. "timestamp": "2017-08-17T07:08:06.186748+00:00",
  104. "sampled_value": [
  105. {
  106. "value": "10",
  107. "context": "Sample.Periodic",
  108. "measurand": "Power.Active.Import",
  109. "unit": "W",
  110. },
  111. {
  112. "value": "50000",
  113. "context": "Sample.Periodic",
  114. "measurand": "Power.Active.Import",
  115. "phase": "L1",
  116. "unit": "W",
  117. },
  118. ],
  119. },
  120. {
  121. "timestamp": "2017-08-17T07:07:07.186748+00:00",
  122. "sampled_value": [
  123. {
  124. "value": "10",
  125. "context": "Sample.Periodic",
  126. "measurand": "Power.Active.Import",
  127. "unit": "W",
  128. },
  129. {
  130. "value": "50000",
  131. "context": "Sample.Periodic",
  132. "measurand": "Power.Active.Import",
  133. "phase": "L1",
  134. "unit": "W",
  135. },
  136. ],
  137. },
  138. ],
  139. "transaction_id": 5,
  140. }
  141. payload = MeterValuesPayload(
  142. connector_id=3,
  143. meter_value=[
  144. MeterValue(
  145. timestamp="2017-08-17T07:08:06.186748+00:00",
  146. sampled_value=[
  147. SampledValue(
  148. value="10",
  149. context="Sample.Periodic",
  150. format=None,
  151. measurand="Power.Active.Import",
  152. phase=None,
  153. location=None,
  154. unit="W",
  155. ),
  156. SampledValue(
  157. value="50000",
  158. context="Sample.Periodic",
  159. format=None,
  160. measurand="Power.Active.Import",
  161. phase="L1",
  162. location=None,
  163. unit="W",
  164. ),
  165. ],
  166. ),
  167. MeterValue(
  168. timestamp="2017-08-17T07:07:07.186748+00:00",
  169. sampled_value=[
  170. SampledValue(
  171. value="10",
  172. context="Sample.Periodic",
  173. format=None,
  174. measurand="Power.Active.Import",
  175. phase=None,
  176. location=None,
  177. unit="W",
  178. ),
  179. SampledValue(
  180. value="50000",
  181. context="Sample.Periodic",
  182. format=None,
  183. measurand="Power.Active.Import",
  184. phase="L1",
  185. location=None,
  186. unit="W",
  187. ),
  188. ],
  189. ),
  190. ],
  191. transaction_id=5,
  192. )
  193. payload = asdict(payload)
  194. assert expected_payload == remove_nones(payload)
  195. def test_remove_nones_with_list_of_strings():
  196. """Make sure that `remove_nones()` doesn't crash when it encounters an
  197. iterable other than a list or dict. See
  198. https://github.com/mobilityhouse/ocpp/issues/289.
  199. """
  200. payload = asdict(
  201. GetConfigurationPayload(key=["ClockAlignedDataInterval", "ConnectionTimeOut"])
  202. )
  203. assert remove_nones(payload) == {
  204. "key": ["ClockAlignedDataInterval", "ConnectionTimeOut"]
  205. }