ring.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #!/usr/bin/env python3
  2. import json
  3. import logging
  4. import tempfile
  5. from argparse import ArgumentParser
  6. from pathlib import Path
  7. from subprocess import Popen
  8. import asterisk_misc_common
  9. from panoramisk.actions import Action
  10. log = logging.getLogger("ring")
  11. ARGS = None
  12. async def run_app(Cls, manager):
  13. instance = Cls(manager)
  14. await instance.run()
  15. async def update(manager):
  16. manager.send_command("sip show peers")
  17. pass
  18. async def on_tutto(manager, msg):
  19. for prefix in ["EndpointList", "CoreShowChannel", "TestEvent"]:
  20. if msg.event.startswith(prefix):
  21. return
  22. log.debug(" (%s)", msg.event)
  23. def public_dir(x):
  24. return [attr for attr in dir(x) if not attr.startswith("_")]
  25. class RingManager:
  26. def __init__(self, manager):
  27. self.manager = manager
  28. self.events = []
  29. self.log = logging.getLogger(self.__class__.__name__)
  30. self.tmp_channels = []
  31. self.channels = []
  32. self.endpoints = []
  33. self.tmp_endpoints = []
  34. async def run(self):
  35. self.manager.register_event("EndpointList", self.on_endpoint)
  36. self.manager.register_event("EndpointListComplete", self.on_endpoints)
  37. async def on_endpoint(self, _, msg):
  38. self.tmp_endpoints.append(msg)
  39. async def on_endpoints(self, _, msg):
  40. self.endpoints = self.tmp_endpoints
  41. self.tmp_endpoints = []
  42. state_map = {
  43. "In use": "Up",
  44. "Ringing": "Ringing",
  45. }
  46. state = {}
  47. for e in self.endpoints:
  48. if e.get("DeviceState") in state_map:
  49. state[e.auths] = state_map[e.get("DeviceState")]
  50. self.save({"devices": state, "onair": {}})
  51. def save(self, state):
  52. tmp = tempfile.NamedTemporaryFile(
  53. mode="w",
  54. dir=ARGS.state_file.parent.absolute(),
  55. prefix="statefile-",
  56. suffix=".json",
  57. delete=False,
  58. )
  59. json.dump(state, tmp)
  60. tmp.close()
  61. Path(tmp.name).rename(ARGS.state_file)
  62. self.log.info("renamed")
  63. if ARGS.on_save is not None:
  64. Popen([str(ARGS.on_save.resolve())])
  65. def refresh(manager, *args):
  66. # manager.send_action(Action({"Action": "CoreShowChannels"}), as_list=False)
  67. manager.send_action(Action({"Action": "PJSIPShowEndpoints"}), as_list=False)
  68. async def init(manager):
  69. manager.register_event("*", on_tutto)
  70. for event in [
  71. "FullyBooted",
  72. "Hangup",
  73. "Newchannel",
  74. "Newexten",
  75. "DialBegin",
  76. "DialEnd",
  77. "DeviceStateChange",
  78. ]:
  79. manager.register_event(event, refresh)
  80. await run_app(RingManager, manager)
  81. async def on_shutdown(m):
  82. print("Shutting down...")
  83. def main():
  84. global ARGS
  85. p = ArgumentParser()
  86. p.add_argument("--state-file", type=Path, default=Path("./ring-state.json"))
  87. p.add_argument("--on-save", type=Path, default=None)
  88. asterisk_misc_common.add_arguments(p)
  89. ARGS = p.parse_args()
  90. asterisk_misc_common.do_common_options(ARGS)
  91. manager = asterisk_misc_common.get_manager(ARGS)
  92. asterisk_misc_common.run_manager(
  93. manager, ARGS, on_startup=init, on_shutdown=on_shutdown
  94. )
  95. if __name__ == "__main__":
  96. main()