ring.py 3.0 KB

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