PageRenderTime 37ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/configs/araisrobo/css/css_vcp.py

https://github.com/araisrobo/linuxcnc
Python | 324 lines | 194 code | 22 blank | 108 comment | 19 complexity | 64b47af65e0b724eb01f910be2481b08 MD5 | raw file
  1. #/usr/bin/env python
  2. # -*- coding: UTF-8 -*
  3. # vim: sts=4 sw=4 et
  4. import os,sys
  5. from gladevcp.persistence import IniFile,widget_defaults,set_debug,select_widgets
  6. import hal
  7. import hal_glib
  8. import gtk
  9. import glib
  10. import time
  11. import linuxcnc
  12. import ConfigParser
  13. import zmq
  14. import pango
  15. debug = 0
  16. class EmcInterface(object):
  17. def __init__(self):
  18. try:
  19. # emcIniFile = linuxcnc.ini(os.environ['INI_FILE_NAME'])
  20. # linuxcnc.nmlfile = os.path.join(os.path.dirname(os.environ['INI_FILE_NAME']), emcIniFile.find("EMC", "NML_FILE"))
  21. self.s = linuxcnc.stat();
  22. self.c = linuxcnc.command()
  23. except Exception, msg:
  24. print "cant initialize EmcInterface: %s - EMC not running?" %(msg)
  25. def running(self,do_poll=True):
  26. if do_poll: self.s.poll()
  27. return self.s.task_mode == linuxcnc.MODE_AUTO and self.s.interp_state != linuxcnc.INTERP_IDLE
  28. def manual_ok(self,do_poll=True):
  29. if do_poll: self.s.poll()
  30. if self.s.task_state != linuxcnc.STATE_ON: return False
  31. return self.s.interp_state == linuxcnc.INTERP_IDLE
  32. def ensure_mode(self, m, *p):
  33. '''
  34. If emc is not already in one of the modes given, switch it to the first mode
  35. example:
  36. ensure_mode(linuxcnc.MODE_MDI)
  37. ensure_mode(linuxcnc.MODE_AUTO, linuxcnc.MODE_MDI)
  38. '''
  39. self.s.poll()
  40. if self.s.task_mode == m or self.s.task_mode in p: return True
  41. if self.running(do_poll=False): return False
  42. self.c.mode(m)
  43. self.c.wait_complete()
  44. return True
  45. def active_codes(self):
  46. self.s.poll()
  47. return self.s.gcodes
  48. def spindle_speed(self):
  49. self.s.poll()
  50. return self.s.spindle_speed
  51. def get_current_system(self):
  52. for i in self.active_codes():
  53. if i >= 540 and i <= 590:
  54. return i/10 - 53
  55. elif i >= 590 and i <= 593:
  56. return i - 584
  57. return 1
  58. def mdi_command(self, command, wait=True):
  59. if (not self.ensure_mode(linuxcnc.MODE_MDI)):
  60. print "cannot switch to MODE_MDI"
  61. return
  62. self.c.mdi(command)
  63. if wait: self.c.wait_complete()
  64. def emc_status(self):
  65. '''
  66. return tuple (task mode, task state, exec state, interp state) as strings
  67. '''
  68. self.s.poll()
  69. task_mode = ['invalid', 'MANUAL', 'AUTO', 'MDI'][self.s.task_mode]
  70. task_state = ['invalid', 'ESTOP', 'ESTOP_RESET', 'OFF', 'ON'][self.s.task_state]
  71. exec_state = ['invalid', 'ERROR', 'DONE',
  72. 'WAITING_FOR_MOTION',
  73. 'WAITING_FOR_MOTION_QUEUE',
  74. 'WAITING_FOR_IO',
  75. 'WAITING_FOR_PAUSE',
  76. 'WAITING_FOR_MOTION_AND_IO',
  77. 'WAITING_FOR_DELAY',
  78. 'WAITING_FOR_SYSTEM_CMD'][self.s.exec_state]
  79. interp_state = ['invalid', 'IDLE', 'READING', 'PAUSED', 'WAITING'][self.s.interp_state]
  80. return (task_mode, task_state, exec_state, interp_state)
  81. class HandlerClass:
  82. '''
  83. class with gladevcp callback handlers
  84. '''
  85. def _query_emc_status(self,data=None):
  86. (task_mode, task_state, exec_state, interp_state) = self.e.emc_status()
  87. self.builder.get_object('task_mode').set_label("Task mode: " + task_mode)
  88. self.builder.get_object('task_state').set_label("Task state: " + task_state)
  89. self.builder.get_object('exec_state').set_label("Exec state: " + exec_state)
  90. self.builder.get_object('interp_state').set_label("Interp state: " + interp_state)
  91. # 為了左右邊的 mdi command 訊號可以同步
  92. # if(self.e.spindle_speed() > 0):
  93. # self.builder.get_object('do1').set_active(True) # M3, SPINDLE.FWD
  94. # self.builder.get_object('do2').set_active(False) # M4, SPINDLE.REV
  95. # elif(self.e.spindle_speed() < 0):
  96. # self.builder.get_object('do1').set_active(False) # M3, SPINDLE.FWD
  97. # self.builder.get_object('do2').set_active(True) # M4, SPINDLE.REV
  98. # else:
  99. # self.builder.get_object('do1').set_active(False)
  100. # self.builder.get_object('do2').set_active(False)
  101. # print self.e.active_modes()
  102. # looping: if (task_mode == "MANUAL") and (task_state == "ON") and (exec_state == "DONE") and (interp_state == "IDLE"):
  103. # looping: # print ("task_mode: manual...")
  104. # looping: # print ("about to cycle-start...")
  105. # looping: # if self.emcstat.interp_state == self.emc.INTERP_IDLE:
  106. # looping: self.e.c.mode(linuxcnc.MODE_AUTO)
  107. # looping: self.e.c.wait_complete() # linuxcnc.command
  108. # looping: self.e.c.auto(linuxcnc.AUTO_RUN, 0)
  109. return True
  110. # def on_button_press(self,widget,data=None):
  111. # '''
  112. # a callback method
  113. # parameters are:
  114. # the generating object instance, likte a GtkButton instance
  115. # user data passed if any - this is currently unused but
  116. # the convention should be retained just in case
  117. # '''
  118. # print "on_button_press called"
  119. # self.nhits += 1
  120. # self.builder.get_object('hits').set_label("Hits: %d" % (self.nhits))
  121. def on_destroy(self,obj,data=None):
  122. self.ini.save_state(self)
  123. # def on_do7_toggled(self, widget, data=None):
  124. # if (not self.e.manual_ok(do_poll=True)):
  125. # # bypass issuing MDI when program is running
  126. # return
  127. # label = gtk.Label("Click OK to TOOL-RELEASE")
  128. # dialog = gtk.Dialog("TOOL-RELEASE",
  129. # None,
  130. # gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
  131. # (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
  132. # gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
  133. # dialog.vbox.pack_start(label)
  134. # label.show()
  135. #
  136. # response = dialog.run()
  137. # if response == gtk.RESPONSE_ACCEPT:
  138. # print 'on_do7_toggled'
  139. # dialog.destroy()
  140. # if widget.get_active() == True:
  141. # self.e.mdi_command('M64 P8', True) # release tool
  142. # else:
  143. # self.e.mdi_command('M65 P8', True) # clamp tool
  144. # else:
  145. # dialog.destroy()
  146. #
  147. # def on_do1_toggled(self, widget, data=None):
  148. # # print 'debug: on_do1_toggled'
  149. # if (not self.e.manual_ok(do_poll=True)):
  150. # # bypass issuing MDI when program is running
  151. # return
  152. # if widget.get_active() == True:
  153. # self.e.mdi_command('M3', True)
  154. # else:
  155. # if(self.e.spindle_speed() != 0):
  156. # self.e.mdi_command('M5', True)
  157. #
  158. # def on_do2_toggled(self, widget, data=None):
  159. # # print 'debug: on_do2_toggled'
  160. # if (not self.e.manual_ok(do_poll=True)):
  161. # # bypass issuing MDI when program is running
  162. # return
  163. # if widget.get_active() == True:
  164. # self.e.mdi_command('M4', True)
  165. # else:
  166. # if(self.e.spindle_speed() != 0):
  167. # self.e.mdi_command('M5', True)
  168. #
  169. #
  170. # def on_spindle_brake_toggled(self, widget, data=None):
  171. # if (not self.e.manual_ok(do_poll=True)):
  172. # # bypass issuing MDI when program is running
  173. # return
  174. #
  175. # if (self.halcomp['spindle.brake'] == 0):
  176. # self.halcomp['spindle.brake'] = 1
  177. ## self.e.mdi_command('M64 P9', True)
  178. # else:
  179. # self.halcomp['spindle.brake'] = 0
  180. ## self.e.mdi_command('M65 P9', True)
  181. def on_restore_defaults(self,button,data=None):
  182. '''
  183. example callback for 'Reset to defaults' button
  184. currently unused
  185. '''
  186. self.ini.create_default_ini()
  187. self.ini.restore_state(self)
  188. def set_theme_font(self):
  189. # set ui theme
  190. config = ConfigParser.ConfigParser()
  191. fn = os.path.expanduser(".touchy_preferences")
  192. config.read(fn)
  193. o = config.get("DEFAULT", 'control_font')
  194. l = config.get("DEFAULT", 'listing_font')
  195. control_font = pango.FontDescription(o)
  196. #control_font = pango.FontDescription("San 24")
  197. # # set spin button font
  198. # for i in ["btn_scan_barcode"]:
  199. # w = self.builder.get_object(i)
  200. # if w:
  201. # w = w.child
  202. # w.modify_font(control_font)
  203. '''set label font'''
  204. self.listing_font = pango.FontDescription(l)
  205. for i in ["task_mode","task_state","exec_state","interp_state",
  206. "label3","j4-enc_pos-label",
  207. "label6","current-tool","label7","prepared-tool","label8",
  208. "label9","label10","label11","label12","label13","label14","label15",
  209. "label16","label17","label18","label19","label20"]:
  210. w = self.builder.get_object(i)
  211. if w:
  212. w.modify_font(self.listing_font)
  213. for i in ["prepared-tool","current-tool","j4-enc_pos-label","analog_07"]:
  214. w = self.builder.get_object(i)
  215. if w:
  216. w.modify_font(control_font)
  217. theme_name = config.get("DEFAULT", 'gtk_theme')
  218. settings = gtk.settings_get_default()
  219. settings.set_string_property("gtk-theme-name", theme_name, "")
  220. def _on_update_status(self):
  221. evts = self.zmq_poller.poll(0)
  222. if evts:
  223. msg = self.zmq_server.recv()
  224. '''TODO: 偵測訊息內容'''
  225. if msg:
  226. pass
  227. self.zmq_server.send("message from vbc.py")
  228. return True
  229. def _delayed_sys_init_(self):
  230. self.builder.get_object("task_mode").hide()
  231. self.builder.get_object("task_state").hide()
  232. self.builder.get_object("exec_state").hide()
  233. self.builder.get_object("interp_state").hide()
  234. return False
  235. def __init__(self, halcomp, builder, useropts):
  236. '''
  237. Handler classes are instantiated in the following state:
  238. - the widget tree is created, but not yet realized (no toplevel window.show() executed yet)
  239. - the halcomp HAL component is set up and the widhget tree's HAL pins have already been added to it
  240. - it is safe to add more hal pins because halcomp.ready() has not yet been called at this point.
  241. after all handlers are instantiated in command line and get_handlers() order, callbacks will be
  242. connected with connect_signals()/signal_autoconnect()
  243. The builder may be either of libglade or GtkBuilder type depending on the glade file format.
  244. '''
  245. # TODO: add a signal to check if the relay for spindle-pump is ON
  246. halcomp.newpin("spindle.fwd", hal.HAL_BIT, hal.HAL_IN)
  247. halcomp.newpin("spindle.rev", hal.HAL_BIT, hal.HAL_IN)
  248. halcomp.newpin("spindle.jog-fwd", hal.HAL_BIT, hal.HAL_IN)
  249. halcomp.newpin("spindle.jog-rev", hal.HAL_BIT, hal.HAL_IN)
  250. halcomp.newpin("spindle.pump", hal.HAL_BIT, hal.HAL_OUT)
  251. halcomp.newpin("spindle.brake", hal.HAL_BIT, hal.HAL_OUT)
  252. self.halcomp = halcomp
  253. self.builder = builder
  254. self.nhits = 0
  255. self.set_theme_font()
  256. self.context = zmq.Context()
  257. self.zmq_server = self.context.socket(zmq.PAIR)
  258. self.zmq_server.bind('tcp://127.0.0.1:5556')
  259. self.zmq_poller = zmq.Poller()
  260. self.zmq_poller.register(self.zmq_server, zmq.POLLIN)
  261. self.zmq_context = zmq.Context()
  262. self.zmq_socket = self.zmq_context.socket(zmq.PUSH)
  263. self.zmq_socket.connect('tcp://127.0.0.1:5555')
  264. self.ini_filename = __name__ + '.ini'
  265. self.defaults = { IniFile.vars: dict(),
  266. IniFile.widgets : widget_defaults(select_widgets(self.builder.get_objects(), hal_only=False,output_only = True))
  267. }
  268. self.ini = IniFile(self.ini_filename,self.defaults,self.builder)
  269. self.ini.restore_state(self)
  270. self.e = EmcInterface()
  271. # program startup
  272. self.timer_id = glib.timeout_add(100, self._delayed_sys_init_)
  273. glib.timeout_add_seconds(1, self._query_emc_status)
  274. glib.timeout_add(100, self._on_update_status)
  275. def get_handlers(halcomp,builder,useropts):
  276. '''
  277. this function is called by gladevcp at import time (when this module is passed with '-u <modname>.py')
  278. return a list of object instances whose methods should be connected as callback handlers
  279. any method whose name does not begin with an underscore ('_') is a callback candidate
  280. the 'get_handlers' name is reserved - gladevcp expects it, so do not change
  281. '''
  282. return [HandlerClass(halcomp,builder,useropts)]