neurotimer.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import logging
  2. import sys
  3. import threading
  4. import time
  5. from kalliope.core import NeuronModule
  6. from kalliope.core.NeuronModule import MissingParameterException, InvalidParameterException
  7. logging.basicConfig()
  8. logger = logging.getLogger("kalliope")
  9. class TimerThread(threading.Thread):
  10. def __init__(self, time_to_wait_seconds, callback):
  11. """
  12. A Thread that will call the given callback method after waiting time_to_wait_seconds
  13. :param time_to_wait_seconds: number of second to wait before call the callback method
  14. :param callback: callback method
  15. """
  16. threading.Thread.__init__(self)
  17. self.time_to_wait_seconds = time_to_wait_seconds
  18. self.callback = callback
  19. def run(self):
  20. # wait the amount of seconds
  21. logger.debug("[Neurotimer] wait %s seconds" % self.time_to_wait_seconds)
  22. time.sleep(self.time_to_wait_seconds)
  23. # then run the callback method
  24. self.callback()
  25. class Neurotimer(NeuronModule):
  26. def __init__(self, **kwargs):
  27. super(Neurotimer, self).__init__(**kwargs)
  28. # get parameters
  29. self.seconds = kwargs.get('seconds', None)
  30. self.minutes = kwargs.get('minutes', None)
  31. self.hours = kwargs.get('hours', None)
  32. self.synapse = kwargs.get('synapse', None)
  33. self.forwarded_parameter = kwargs.get('forwarded_parameters', None)
  34. # do some check
  35. if self._is_parameters_ok():
  36. # make the sum of all time parameter in seconds
  37. retarding_time_seconds = self._get_retarding_time_seconds()
  38. # now wait before running the target synapse
  39. ds = TimerThread(time_to_wait_seconds=retarding_time_seconds, callback=self.callback_run_synapse)
  40. # ds.daemon = True
  41. ds.start()
  42. def _is_parameters_ok(self):
  43. """
  44. Check given neuron parameters are valid
  45. :return: True if the neuron has been well configured
  46. """
  47. # at least one time parameter must be set
  48. if self.seconds is None and self.minutes is None and self.hours is None:
  49. raise MissingParameterException("Neurotimer must have at least one time "
  50. "parameter: seconds, minutes, hours")
  51. self.seconds = self.get_integer_time_parameter(self.seconds)
  52. self.minutes = self.get_integer_time_parameter(self.minutes)
  53. self.hours = self.get_integer_time_parameter(self.hours)
  54. if self.synapse is None:
  55. raise MissingParameterException("Neurotimer must have a synapse name parameter")
  56. return True
  57. @staticmethod
  58. def get_integer_time_parameter(time_parameter):
  59. """
  60. Check if a given time parameter is a valid integer:
  61. - must be > 0
  62. - if type no an integer, must be convertible to integer
  63. :param time_parameter: string or integer
  64. :return: integer
  65. """
  66. if time_parameter is not None:
  67. if not isinstance(time_parameter, int):
  68. # try to convert into integer
  69. try:
  70. time_parameter = int(time_parameter)
  71. except ValueError:
  72. raise InvalidParameterException("[Neurotimer] %s is not a valid integer" % time_parameter)
  73. # check if positive
  74. if time_parameter < 0:
  75. raise InvalidParameterException("[Neurotimer] %s must be > 0" % time_parameter)
  76. return time_parameter
  77. def _get_retarding_time_seconds(self):
  78. """
  79. Return the sum of given time parameters
  80. seconds + minutes + hours
  81. :return: integer, number of total seconds
  82. """
  83. returned_time = 0
  84. if self.seconds is not None:
  85. returned_time += self.seconds
  86. if self.minutes is not None:
  87. returned_time += self.minutes * 60
  88. if self.hours is not None:
  89. returned_time += self.hours * 3600
  90. logger.debug("[Neurotimer] get_retarding_time_seconds: %s" % returned_time)
  91. return returned_time
  92. def callback_run_synapse(self):
  93. """
  94. Callback method which will be started by the timer thread once the time is over
  95. :return:
  96. """
  97. logger.debug("[Neurotimer] waiting time is over, start the synapse %s" % self.synapse)
  98. # trick to remove unicode problem when loading jinja template with non ascii char
  99. if sys.version_info[0] == 2:
  100. reload(sys)
  101. sys.setdefaultencoding('utf-8')
  102. self.run_synapse_by_name(synapse_name=self.synapse,
  103. high_priority=False,
  104. overriding_parameter_dict=self.forwarded_parameter)