preflight.py 4.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. # SPDX-License-Identifier: Apache-2.0
  2. # Copyright 2020 Contributors to OpenLEADR
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. # Unless required by applicable law or agreed to in writing, software
  8. # distributed under the License is distributed on an "AS IS" BASIS,
  9. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. # See the License for the specific language governing permissions and
  11. # limitations under the License.
  12. """
  13. Tests message contents before sending them. It will correct benign errors and
  14. warn you about them. Uncorrectable errors will raise an Exception.
  15. """
  16. from datetime import datetime, timedelta, timezone
  17. import warnings
  18. def preflight_message(message_type, message_payload):
  19. if f'preflight_{message_type}' in globals():
  20. globals()[f'preflight_{message_type}'](message_payload)
  21. return message_type, message_payload
  22. def preflight_oadrDistributeEvent(message_payload):
  23. if 'parse_duration' not in globals():
  24. from .utils import parse_duration
  25. # Check that the total event_duration matches the sum of the interval durations (rule 8)
  26. for event in message_payload['events']:
  27. active_period_duration = event['active_period']['duration']
  28. signal_durations = []
  29. for signal in event['event_signals']:
  30. signal_durations.append(sum([parse_duration(i['duration']) for i in signal['intervals']], timedelta(seconds=0)))
  31. if not all([d==active_period_duration for d in signal_durations]):
  32. if not all([d==signal_durations[0] for d in signal_durations]):
  33. raise ValueError("The different EventSignals have different total durations. Please correct this.")
  34. else:
  35. warnings.warn(f"The active_period duration for event {event['event_descriptor']['event_id']} ({active_period_duration})"
  36. f" was different from the sum of the interval's durations ({signal_durations[0]})."
  37. f" The active_period duration has been adjusted to ({signal_durations[0]}).")
  38. event['active_period']['duration'] = signal_durations[0]
  39. # Check that payload values with signal name SIMPLE are constricted (rule 9)
  40. for event in message_payload['events']:
  41. for event_signal in event['event_signals']:
  42. if event_signal['signal_name'] == "SIMPLE":
  43. for interval in event_signal['intervals']:
  44. if interval['signal_payload'] not in (0, 1, 2, 3):
  45. raise ValueError("Payload Values used with Signal Name SIMPLE must be one of"
  46. "0, 1, 2 or 3")
  47. # Check that the current_value is 0 for SIMPLE events that are not yet active (rule 14)
  48. for event in message_payload['events']:
  49. for event_signal in event['event_signals']:
  50. if 'current_value' in event_signal and event_signal['current_value'] != 0:
  51. if event_signal['signal_name'] == "SIMPLE" and event['event_descriptor']['event_status'] != "ACTIVE":
  52. warnings.warn("The current_value for a SIMPLE event that is not yet active must be 0. This will be corrected.")
  53. event_signal['current_value'] = 0
  54. # Check that there is a valid oadrResponseRequired value for each Event
  55. for event in message_payload['events']:
  56. if 'response_required' not in event:
  57. event['response_required'] = 'always'
  58. elif event['response_required'] not in ('never', 'always'):
  59. warnings.warn(f"The response_required property in an Event should be 'never' or 'always', not {event['response_required']}. Changing to 'always'.")
  60. event['response_required'] = 'always'
  61. # Check that there is a valid oadrResponseRequired value for each Event
  62. for event in message_payload['events']:
  63. if 'created_date_time' not in event['event_descriptor'] or not event['event_descriptor']['created_date_time']:
  64. print("ADDING CREATED DATE TIME")
  65. event['event_descriptor']['created_date_time'] = datetime.now(timezone.utc)