console.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. #!/usr/bin/python
  2. # Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. # Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. #
  5. # Permission is hereby granted, free of charge, to any person
  6. # obtaining a copy of this software and associated documentation
  7. # files (the "Software"), to deal in the Software without
  8. # restriction, including without limitation the rights to use,
  9. # copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. # copies of the Software, and to permit persons to whom the
  11. # Software is furnished to do so, subject to the following
  12. # conditions:
  13. #
  14. # The above copyright notice and this permission notice shall be
  15. # included in all copies or substantial portions of the Software.
  16. #
  17. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. # OTHER DEALINGS IN THE SOFTWARE.
  25. import sys
  26. import os
  27. import socket
  28. import threading
  29. from gi.repository import Gtk
  30. # Client Console commands
  31. CMD_CLEAR = "clear" # Clear console output
  32. CMD_EXIT_1 = "exit" # Close console
  33. CMD_EXIT_2 = "Device.stop()" # Close console
  34. CMD_HELP = "help" # Console help
  35. CMD_HISTORY = "history" # History
  36. CMD_VOID = ""
  37. class ReaderThread(threading.Thread):
  38. #------------------------------------------------------------------------------
  39. def __init__(self, console):
  40. threading.Thread.__init__(self)
  41. self.t_console = console
  42. self.t_stop = threading.Event()
  43. self.t_is_running = True
  44. #------------------------------------------------------------------------------
  45. def stop(self):
  46. self.t_stop.set()
  47. self.t_is_running = False
  48. #------------------------------------------------------------------------------
  49. def stopped(self):
  50. return self.t_stop.isSet()
  51. #------------------------------------------------------------------------------
  52. def run(self):
  53. while self.t_is_running:
  54. self.t_tmp = self.t_console.m_sock.recv(1024)
  55. if self.t_tmp != "":
  56. self.t_tmp = self.t_tmp.decode("utf-8")
  57. self.t_error = self.t_tmp.split('\x00', 1)[0]
  58. self.t_console.print_error(self.t_error)
  59. class ConsoleHistory:
  60. #------------------------------------------------------------------------------
  61. def __init__(self):
  62. self.m_list = list()
  63. self.m_count = 0
  64. self.m_index = 0
  65. #------------------------------------------------------------------------------
  66. def add(self, cmd):
  67. self.m_list.append(cmd)
  68. self.m_count += 1
  69. self.m_index = self.m_count
  70. #------------------------------------------------------------------------------
  71. def previous(self):
  72. if self.m_count != 0:
  73. self.m_index -= 1
  74. if self.m_index < 0:
  75. self.m_index = 0
  76. return self.m_list[self.m_index]
  77. return ""
  78. #------------------------------------------------------------------------------
  79. def following(self):
  80. if self.m_count != 0:
  81. self.m_index += 1
  82. if self.m_index > self.m_count-1:
  83. self.m_index = self.m_count - 1
  84. return self.m_list[self.m_index]
  85. return ""
  86. class Console:
  87. #------------------------------------------------------------------------------
  88. def __init__(self, address):
  89. builder = Gtk.Builder()
  90. builder.add_from_file("ui/console.glade")
  91. self.m_view = builder.get_object("textview1")
  92. self.m_buffer = builder.get_object("textbuffer1")
  93. self.m_entry = builder.get_object("entry1")
  94. self.m_window = builder.get_object('window1')
  95. self.m_window.set_title("Crown Console")
  96. self.m_window.show_all()
  97. builder.connect_signals(self)
  98. self.m_address = address
  99. self.m_error_buffer = ""
  100. self.history = ConsoleHistory()
  101. self.m_sock = socket.create_connection((self.m_address, 10000))
  102. self.m_thread = ReaderThread(self)
  103. self.m_thread.start()
  104. self.m_formatter = self.m_buffer.create_tag("console", foreground="green")
  105. Gtk.main()
  106. #------------------------------------------------------------------------------
  107. def on_destroy(self, *args):
  108. self.m_sock.close()
  109. self.m_thread.stop()
  110. Gtk.main_quit(*args)
  111. #------------------------------------------------------------------------------
  112. def on_key_pressed(self, entry, event):
  113. # If return is pressed, run command
  114. if event.keyval == 0xff0d:
  115. cmd = entry.get_text()
  116. self.parse_command(cmd)
  117. return True
  118. if event.keyval == 0xff52:
  119. cmd = self.history.previous()
  120. self.print_to_entry(cmd)
  121. return True
  122. if event.keyval == 0xff54:
  123. cmd = self.history.following()
  124. self.print_to_entry(cmd)
  125. return True
  126. #------------------------------------------------------------------------------
  127. def parse_command(self, cmd):
  128. self.history.add(cmd)
  129. if cmd == CMD_CLEAR:
  130. self.m_buffer.set_text("")
  131. self.m_entry.set_text("")
  132. elif cmd == CMD_EXIT_1:
  133. self.on_destroy()
  134. elif cmd == CMD_EXIT_2:
  135. self.run_command(cmd)
  136. self.on_destroy()
  137. elif cmd == CMD_HELP:
  138. self.print_help()
  139. elif cmd == CMD_VOID:
  140. self.print_command("");
  141. else:
  142. self.run_command(cmd)
  143. #------------------------------------------------------------------------------
  144. def run_command(self, cmd):
  145. self.m_sock.send(cmd.encode('utf-8'))
  146. self.print_command(cmd)
  147. #------------------------------------------------------------------------------
  148. def print_command(self, text):
  149. # Print command to console
  150. start_iter = self.m_buffer.get_end_iter()
  151. a_string = "> " + text + "\n"
  152. # Append command to the end of buffer
  153. self.m_buffer.insert(start_iter, a_string, len(a_string))
  154. self.m_view.scroll_mark_onscreen(self.m_buffer.get_insert())
  155. # Reset entry
  156. self.print_to_entry("")
  157. #------------------------------------------------------------------------------
  158. def print_error(self, text):
  159. start_iter = self.m_buffer.get_end_iter()
  160. a_string = "> " + text + "\n"
  161. self.m_buffer.insert(start_iter, a_string, len(a_string))
  162. self.m_view.scroll_mark_onscreen(self.m_buffer.get_insert())
  163. #------------------------------------------------------------------------------
  164. def print_to_entry(self, text):
  165. self.m_entry.set_text(text)
  166. #------------------------------------------------------------------------------
  167. # def popup_dialog(self, message, expl):
  168. # dialog = Gtk.MessageDialog(self.m_window, 0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, message)
  169. # dialog.format_secondary_text(expl)
  170. # dialog.run()
  171. # dialog.destroy()
  172. #------------------------------------------------------------------------------
  173. #------------------------------------------------------------------------------
  174. def main():
  175. if len(sys.argv) != 2:
  176. print("Usage: console.py <ip-address>")
  177. exit(-1)
  178. address = sys.argv[1]
  179. console = Console(address)
  180. main()