262
|
1 |
#!/usr/bin/env python
|
|
2 |
# -*- coding: utf-8 -*-
|
|
3 |
|
|
4 |
#This file is part of Beremiz, a Integrated Development Environment for
|
|
5 |
#programming IEC 61131-3 automates supporting plcopen standard and CanFestival.
|
|
6 |
#
|
|
7 |
#Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD
|
|
8 |
#
|
|
9 |
#See COPYING file for copyrights details.
|
|
10 |
#
|
|
11 |
#This library is free software; you can redistribute it and/or
|
|
12 |
#modify it under the terms of the GNU General Public
|
|
13 |
#License as published by the Free Software Foundation; either
|
|
14 |
#version 2.1 of the License, or (at your option) any later version.
|
|
15 |
#
|
|
16 |
#This library is distributed in the hope that it will be useful,
|
|
17 |
#but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
18 |
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
19 |
#General Public License for more details.
|
|
20 |
#
|
|
21 |
#You should have received a copy of the GNU General Public
|
|
22 |
#License along with this library; if not, write to the Free Software
|
|
23 |
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
24 |
|
|
25 |
import os, sys, getopt
|
|
26 |
|
|
27 |
try:
|
|
28 |
import wx, re
|
|
29 |
from wx.lib.embeddedimage import PyEmbeddedImage
|
|
30 |
from threading import Thread
|
|
31 |
from types import *
|
|
32 |
havewx = True
|
|
33 |
except:
|
|
34 |
havewx = False
|
|
35 |
|
|
36 |
BeremizIcon = PyEmbeddedImage(
|
|
37 |
"iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAABHNCSVQICAgIfAhkiAAADopJ"
|
|
38 |
"REFUaIG1mntwXNV9xz/n3rt79+5KWq1WsiRLWlkyfgnHsiwMtnkUYptQMBGFMjRhCDANJmMe"
|
|
39 |
"pYV/gJZkpoHMJJm2NG1JBzKBQNIUGlLbmMG1MWAZ25LAtmwZW5Yta/WyHtZ7tSvt7r2nf1yt"
|
|
40 |
"vJJWtmyH386Z3XvuOff+vr/zO7/XWSG4JAlAAzxANlAIFAMBS8oCYF5jY2NhdXV1UWtrq7u9"
|
|
41 |
"vV1vbW1VY7GYMAxDulwuy+VyxUpLS0MVFRVdGzZsqPFnZTUBLUAr0AUMAGHAAhyAAehAbKI/"
|
|
42 |
"CsiUzF0CgDrxMD+wAFhiSbkUKN2/f3/Ztm3bCj/66CNXfX39HORgk8PhoKysLL5p06bWxx9/"
|
|
43 |
"fHtxIFALnAI6gDEgHZg/8X1+AuQgYKZ8oJi9aQKyBJQL+K6U8qdSyg+qq6vb1q9fb05I5Kpa"
|
|
44 |
"enq6vP/++wf27NnzCwF/IeA2AQ8I+Acp5Y8feuih1wRsFOCcjc/ZmHcKyBdws4BnpJS/PXr0"
|
|
45 |
"aNM999wTF0JcNePTm2EYcsuWLe2jo6P/LqV8OxwO77333ntbASngOQHpswo6xdo7gRxgKbDO"
|
|
46 |
"knLt22+/vW7Lli3eUCiUchV1XWfJNYWUzE8jkGtQnGfg0SWmVBmNarR2R2nuGOZ0sJ8zZ4NY"
|
|
47 |
"lpXyOcuXL5cvvfTSwCuvvJJ+5MgRB8DKlSv/q/7IkV8Be7H3xBSaDsCBre9lwI3RWGztM888"
|
|
48 |
"c8trr73mkVIipUyaKCi/toQ7bsimaq1Bmm4iLROwIDFOKCAUhFARqgNFMwj2G7y/d5D/23eS"
|
|
49 |
"YGt7SiDJtGDBghPBlpafA78Fxi8GQAUygcXA2tDo6M1VVVW3V1dXu6WUWJaFZVlIKVlUWsDf"
|
|
50 |
"PRBg3VKQVhxkaolOexVCURCqjmb40TMX8Yf9Mf7ll/9NR0fnrLNycnK6z/f2/gz4DyAy/b6S"
|
|
51 |
"9O0BCoAyS8qljz766K0HDx50q6pKonncbp7/60r+54dFrF0cR5rROTIPIJGWBdJCCA2Hnsb3"
|
|
52 |
"v/stDny2g7zc3FlnjY6Opl+7fHk6tmrPIA17LziALGChJeXCp59+ev2uXbsyVVVFURQsyyI3"
|
|
53 |
"x8dPNhdTVmgizRmqODcSAqFoqE4Pqp5JU/A8D27eQld396xTwuGw2+l0uoEMYJhp/kAVtupk"
|
|
54 |
"ACVAme5y3fnGG2+UCyFQFAUhBIH5Pn71XDGFWbHp8y8fg6KhqE4+qevggcd/Sld37yXnBAKB"
|
|
55 |
"zo6Oji+A3ukMKNhL4wPyjh47ds3rr7++RlVVNE1DVVVystJ59Yn5ZLhmdYaXQRJpjhML91FZ"
|
|
56 |
"Ms4/PnUTq1cUX3KW1+tdj60hM4ymKsCLrfsL+gcGHgwGg/MSkjcMnZ98fz4Bf8JvTaDWDBzu"
|
|
57 |
"HFRn+pybUDSs+JhtoawYwopwzXyV+24LcNdtZTh0D83tg4xH4zMAFBYWGoVFRefbWls/BaYM"
|
|
58 |
"EAKKgGX/u3XrhmefffY50zRFwupsvjuPu1czY6NmltxO4M9evqTkppMZGyU60sFA03b6Gt9D"
|
|
59 |
"WhZCURGqE1VzExUedtYO8PuPmjh8vG1y3ooVKygpKenZtnXrLUATdsw0uQL5QH5ff/8TQ0ND"
|
|
60 |
"OQnpF+en8bdVOsiZIYjLtxDvgvWXDUBRnTgMP+mF68hcsIHhtk8xoyNIK440xxBWmCWFGlXr"
|
|
61 |
"S83himXCOegRfX19ABQVFXl0l8vo7uraTZJDU4UdXV5rGMbDYDsoRVF48tuZ5Gemjp+uFEAy"
|
|
62 |
"aa5M3NllDJ7ZwWRUIU2kGeWr/pGBwz7LPc+by+J5y1BVFZfLha7r+c3NzR8DPUysggJoTzz5"
|
|
63 |
"5A2Kokxu3KXF6VSWWlz9pr04eXIrSC+6eVqv5MDwWGgsFmGooIfx2Bh+vx8pJbqu5wPfJMkn"
|
|
64 |
"aIBobGy8TtM0LMtCCMHNyzVkCtWZC50//juG2/YCoDjceOaVk1F8G3pGIOV4w7+U4dbPJq9H"
|
|
65 |
"4zJ6Ik3PEUikM47pj6L0XPBhK8rL1x2tr38PO5+wNCBjeHh4maqqCCHQNJW1ixWmbfY50/hw"
|
|
66 |
"K6GuLyevh9uqGQru4ZpNb6Uc7zD8U67f6ol1Cr+xIHFt5Y1PAZCVlXUtsARoB6IK8A1VVUXC"
|
|
67 |
"9i8qcJHuujLpz0ZjQy12zJTq3mDz5O/fn4u2ns1yTVkqmRudYv3dbvcCYBF29IDy8COP+JMd"
|
|
68 |
"V0muQP4pdV8oZC2qQijajFtWfIyh4B4AXu2ItnyZZQQQQkkeI3UL6bpgxoUQaobXOw/bfwlt"
|
|
69 |
"ZGTEr6oqUkqEEPjT5YVw+Aooa1EVnrxKAFSnB3fON1Cd6TPGSStGR+0/yR0tHZ2fWIoSz76g"
|
|
70 |
"Nkno7XDZZULkAi6Px5M5PDSUA3Rr4+PjOckb2Jd2ZbqfICN7GUb2souOGeiqN1/d/uOuz8Mt"
|
|
71 |
"GUqGq2C2cQJQhIJ0WrbTEwIhBG63OwO7wKAoQE4iXNY0jQwjkel9fRQx/Gppxe0Fvkz/zKWZ"
|
|
72 |
"hkCgIHVJPB7HNE1M08TlcmVg5y5CAULJeyBuJbB/fTTfW8j3rnuMf7vvTUr9iy46VhECxVQm"
|
|
73 |
"mTdNE2wn5gSEJqXsUBRbvxRFYXRc4WIrYEnk6bAyFLAlMIP2t3zGye7jgO3Vi32lLM8vZ15a"
|
|
74 |
"3oyx89Ly+PuNr/DYu3+Fac20fAKBoqhEw/YKKIqCoijE4/EwdhqA9uGOHZ13bdo0+UIbQGqq"
|
|
75 |
"GYz3vCdV520BMr85y5gv2mrY8dX7M/o3r/0b7lvxnRn9Bd4ibiy5lb1nPk4JQBUqsRFbfRJB"
|
|
76 |
"pmmaISaySQVoS540MKqmZGx7T6z9PaczS7i1lJK/FH341R9nvXdN9pIUvfaGdahOxoaiU1Ro"
|
|
77 |
"AsAYIDXgdPK0pm59xqPeOhcNNviM4kuV8S5Gq4pumPVemjNtJvsCNEVD9GuMj4xPpraqqkbi"
|
|
78 |
"8XgEGEkAOIBdm/QBDIZVuoY08ry2Oe2OmKFjma6CuTKf4cogNz3fZgLBgqxSyudXsn7xn886"
|
|
79 |
"p6GrfkafIhScmk64KYZpmliWxUTA2WbZhaXBBIC4lPJDRVEeTITSp3rSyMscBin5db/VJ7LF"
|
|
80 |
"pfO+CXpk9Q94ZPUP5jocgPrOL6dc27qvYTjcdJzowjRNhBAJZ3u2o73dBLoBSwH4cMeOPyqK"
|
|
81 |
"gsfjwe/3c2aoALQMxoUjNpDtKRTYn6+DDgb30Td6fkqfIhRcDhei08Fg19CkDwDMWCzWBIwy"
|
|
82 |
"kRMkTM5OVVVHdF2npqaGSNxFMFZBt6M45PP4VJfDQFU0hFD+pEC+aDvIy7temNKX2LjpupfT"
|
|
83 |
"H7VP2bxpaWldIyMjo9iGJwp2PgAQMgzjX/Py8l5sbGykoaGBbdvyuOPOG9wl31pMJD3EQKSf"
|
|
84 |
"0PgI4/ExFDG7qZ0LtQ+1UhPcx5u1vyRqRpPZR1M00vR0osclnWfOTdp+KaU0DKN2ZGRkDDjJ"
|
|
85 |
"RLk9eW/mv/DiiyfeeecdbzAYnOxUNZXrb72OVXeuIHOJh/PhXjJ0L6sKr8eUJnIOlbloPMpA"
|
|
86 |
"pI/+cB9tg0G6R87NGCMQqIpKmp5OjjqfT392kOH+kcnaVFFRUUc0Gn23tqamCXgbCMGFFQAY"
|
|
87 |
"9vv9v8nLy3sqGYAZNzmwu4YDu2vIL8rjpm+vxXeLn+rmj+kN9TAaDWFa5lWF4AmP63GmMc+d"
|
|
88 |
"T90vjtHX3Z+QPE6n08rJydl3+PDhEFBPUpE3eQVcwMq7Nm3a88EHHxgXe6GmqZTduISlf1lC"
|
|
89 |
"xBghGo9eMQAhbIvjcXrIzyjk2K+bOHbgK5Irg+Xl5c1DQ0Nbaw4ePINdpR5MzE9WZgsYzMvL"
|
|
90 |
"23epl1pSUrSkEHe2a0rJ/bIYR9i2XtXJNHwEvCWc/l0Hh/bWT1qdeDxOIBAYcrlcu2oOHhwA"
|
|
91 |
"qplQnQQlq5AEIgsXLjwObJztxf4cP1tefoxI3hDB/masOVenLzCOEGiKiksz8Lmz8Ms8dv1k"
|
|
92 |
"LycbGiclL6WksLAwumzZsh01NTX9wDHsotaUhCUZgAWMvfD8881chAJFATLcGVjqGG6nh7gV"
|
|
93 |
"J2qOY0kLS14kmxMCRdhWxqnqZLi85KblEzoU4zf/+S7ne89PqoyUEp/PZ95000276+rqOhtP"
|
|
94 |
"nmwFPseOf6Y/dpIU7DzzZs3heD8Wi6WO6rDD7o13buD676wkkj7CYKSf0HiIaHwcU8ZtIEkS"
|
|
95 |
"FxOMuxwG6XoGWW4/Yyctdr65h+PHLoTeCZNZUFAQ37hx4ycnTpxo+HzfvhbgfaCTpJJiKgAC"
|
|
96 |
"SANWFxYV/aGtrS0TQNd16fV6RU9PTwqhClasXEHlrSuZf10O+EzGYhFiVgzTshACVKHi1HQM"
|
|
97 |
"zc1Y0OT0vha+3HeIlpaWlMJZs2bN+Jo1a3bU1dUF93/+eTuwFbsGlLJUMh2AASwvX7nynSNH"
|
|
98 |
"jizKzs6Obt68+ZDf74/s3Llzza5du4yLbdrMzExKF5biy/aBkCiKQnQsxrn2Ttra2olEZpwQ"
|
|
99 |
"TZLT6eTuu+8+n5ub+2FtbW3Xl198EQR2AkEuUqSaDsAJBNasXfvPXV1dy6uqqurOnDnTE4lE"
|
|
100 |
"Rj7evTv01NNPV23fvn3V2bNnr84VJ5Gqqtxyyy3hioqKA8FgsKmhoeH8qcbGr4DdQD+zHXCn"
|
|
101 |
"AAAXTmtWA+6KVauuO3zoUA+wB/vUfNEPf/SjO7q6uu6pr69fVFdX54jHr6yK4fF4qKysjFRW"
|
|
102 |
"Vh7q7e09cerUqYG62to+oBaoww7YLmmjpwNI/C9Cxz4rrsS2vX3YG0jHzhtueOLJJ9fqur6s"
|
|
103 |
"tbW14ty5c9nNzc3Ozs7OWSM9VVXJycmRZWVl4dLS0jav13u0vb194OzZs8N1tbUD2GayDlvq"
|
|
104 |
"cz6ES5WnJLo07BUZ54IkEgfkLuz/MiwFKr738MMlPp8vDfBHIpFcKaXHNE0jGo3idDrDHo+n"
|
|
105 |
"z+Vy9YRCoUhvb2+ku7s73NPTM9p48mQPdkZ4DHuFL/sQ7kqzxMQ0xwSYTOxzhvyJ5l934406"
|
|
106 |
"IGKxmBUOh83jDQ1j2JnfAHAOOJvEdPxyGb9aADOeg+1HkhvYADVs5sax1XB6uyr6fzqK/HuW"
|
|
107 |
"ycvmAAAAAElFTkSuQmCC")
|
|
108 |
|
|
109 |
def usage():
|
|
110 |
print """
|
|
111 |
Usage of Beremiz PLC execution service :\n
|
|
112 |
%s {[-n name] [-i ip] [-p port]|-h|--help} working_dir
|
|
113 |
-n - zeroconf service name
|
|
114 |
-i - ip of interface to bind to (x.x.x.x)
|
|
115 |
-p - port number
|
|
116 |
-h - print this help text and quit
|
|
117 |
|
|
118 |
working_dir - directory where are stored PLC files
|
|
119 |
"""%sys.argv[0]
|
|
120 |
|
|
121 |
try:
|
|
122 |
opts, args = getopt.getopt(sys.argv[1:], "i:p:n:h")
|
|
123 |
except getopt.GetoptError, err:
|
|
124 |
# print help information and exit:
|
|
125 |
print str(err) # will print something like "option -a not recognized"
|
|
126 |
usage()
|
|
127 |
sys.exit(2)
|
|
128 |
|
|
129 |
# default values
|
|
130 |
ip = ""
|
|
131 |
port = 3000
|
|
132 |
name = os.environ[{
|
|
133 |
"linux2":"USER",
|
|
134 |
"win32":"USERNAME",
|
|
135 |
}.get(sys.platform, "USER")]
|
|
136 |
|
|
137 |
for o, a in opts:
|
|
138 |
if o == "-h":
|
|
139 |
usage()
|
|
140 |
sys.exit()
|
|
141 |
elif o == "-i":
|
|
142 |
if len(a.split(".")) == 4 or a == "localhost":
|
|
143 |
ip = a
|
|
144 |
elif o == "-p":
|
|
145 |
# port: port that the service runs on
|
|
146 |
port = int(a)
|
|
147 |
elif o == "-n":
|
|
148 |
name = a
|
|
149 |
else:
|
|
150 |
usage()
|
|
151 |
sys.exit()
|
|
152 |
|
|
153 |
if len(args) > 1:
|
|
154 |
usage()
|
|
155 |
sys.exit()
|
|
156 |
elif len(args) == 1:
|
|
157 |
WorkingDir = args[0]
|
|
158 |
elif len(args) == 0:
|
|
159 |
WorkingDir = os.getcwd()
|
|
160 |
args=[WorkingDir]
|
|
161 |
|
|
162 |
from runtime import PLCObject, ServicePublisher
|
|
163 |
import Pyro.core as pyro
|
|
164 |
|
|
165 |
if not os.path.isdir(WorkingDir):
|
|
166 |
os.mkdir(WorkingDir)
|
|
167 |
|
|
168 |
|
|
169 |
|
|
170 |
class Server():
|
|
171 |
def __init__(self, name, ip, port, workdir, args):
|
|
172 |
self.continueloop = True
|
|
173 |
self.daemon = None
|
|
174 |
self.name = name
|
|
175 |
self.ip = ip
|
|
176 |
self.port = port
|
|
177 |
self.workdir = workdir
|
|
178 |
self.args = args
|
|
179 |
self.plcobj = None
|
263
|
180 |
self.servicepublisher = None
|
262
|
181 |
|
|
182 |
def Loop(self):
|
|
183 |
while self.continueloop:
|
|
184 |
self.Start()
|
|
185 |
|
|
186 |
def Restart(self):
|
|
187 |
self.Stop()
|
|
188 |
|
|
189 |
def Quit(self):
|
|
190 |
self.continueloop = False
|
|
191 |
self.Stop()
|
|
192 |
|
|
193 |
def Start(self):
|
|
194 |
pyro.initServer()
|
|
195 |
self.daemon=pyro.Daemon(host=self.ip, port=self.port)
|
|
196 |
self.plcobj = PLCObject(self.workdir, self.daemon, self.args)
|
|
197 |
uri = self.daemon.connect(self.plcobj,"PLCObject")
|
|
198 |
|
|
199 |
print "The daemon runs on port :",self.port
|
|
200 |
print "The object's uri is :",uri
|
|
201 |
print "The working directory :",self.workdir
|
|
202 |
|
|
203 |
# Configure and publish service
|
|
204 |
# Not publish service if localhost in address params
|
|
205 |
if self.ip != "localhost" and self.ip != "127.0.0.1":
|
263
|
206 |
print "Publish service on local network"
|
|
207 |
self.servicepublisher = ServicePublisher.ServicePublisher()
|
262
|
208 |
self.servicepublisher.RegisterService(self.name, self.ip, self.port)
|
|
209 |
|
|
210 |
sys.stdout.flush()
|
|
211 |
|
|
212 |
self.daemon.requestLoop()
|
|
213 |
|
|
214 |
def Stop(self):
|
263
|
215 |
if self.servicepublisher is not None:
|
|
216 |
self.servicepublisher.UnRegisterService()
|
|
217 |
del self.servicepublisher
|
262
|
218 |
self.daemon.shutdown(True)
|
|
219 |
|
|
220 |
class ParamsEntryDialog(wx.TextEntryDialog):
|
|
221 |
if wx.VERSION < (2, 6, 0):
|
|
222 |
def Bind(self, event, function, id = None):
|
|
223 |
if id is not None:
|
|
224 |
event(self, id, function)
|
|
225 |
else:
|
|
226 |
event(self, function)
|
|
227 |
|
|
228 |
|
|
229 |
def __init__(self, parent, message, caption = "Please enter text", defaultValue = "",
|
|
230 |
style = wx.OK|wx.CANCEL|wx.CENTRE, pos = wx.DefaultPosition):
|
|
231 |
wx.TextEntryDialog.__init__(self, parent, message, caption, defaultValue, style, pos)
|
|
232 |
|
|
233 |
self.Tests = []
|
|
234 |
if wx.VERSION >= (2, 8, 0):
|
|
235 |
self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetAffirmativeId())
|
|
236 |
elif wx.VERSION >= (2, 6, 0):
|
|
237 |
self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetAffirmativeButton().GetId())
|
|
238 |
else:
|
|
239 |
self.Bind(wx.EVT_BUTTON, self.OnOK, id=self.GetSizer().GetItem(3).GetSizer().GetChildren()[0].GetSizer().GetChildren()[0].GetWindow().GetId())
|
|
240 |
|
|
241 |
def OnOK(self, event):
|
|
242 |
value = self.GetValue()
|
|
243 |
texts = {"value" : value}
|
|
244 |
for function, message in self.Tests:
|
|
245 |
if not function(value):
|
|
246 |
message = wx.MessageDialog(self, message%texts, "Error", wx.OK|wx.ICON_ERROR)
|
|
247 |
message.ShowModal()
|
|
248 |
message.Destroy()
|
|
249 |
return
|
|
250 |
self.EndModal(wx.ID_OK)
|
|
251 |
|
|
252 |
def GetValue(self):
|
|
253 |
return self.GetSizer().GetItem(1).GetWindow().GetValue()
|
|
254 |
|
|
255 |
def SetTests(self, tests):
|
|
256 |
self.Tests = tests
|
|
257 |
|
|
258 |
class DemoTaskBarIcon(wx.TaskBarIcon):
|
|
259 |
TBMENU_CHANGE_NAME = wx.NewId()
|
|
260 |
TBMENU_CHANGE_PORT = wx.NewId()
|
|
261 |
TBMENU_CHANGE_INTERFACE = wx.NewId()
|
|
262 |
TBMENU_CHANGE_WD = wx.NewId()
|
|
263 |
TBMENU_QUIT = wx.NewId()
|
|
264 |
|
|
265 |
def __init__(self, pyroserver):
|
|
266 |
wx.TaskBarIcon.__init__(self)
|
|
267 |
# Set the image
|
|
268 |
icon = self.MakeIcon(BeremizIcon.GetImage())
|
|
269 |
self.SetIcon(icon, "Beremiz Service")
|
|
270 |
# bind some events
|
|
271 |
#self.Bind(wx.EVT_TASKBAR_CLICK, self.OnClick)
|
|
272 |
#self.Bind(wx.EVT_TASKBAR_LEFT_DCLICK, self.OnTaskBarActivate)
|
|
273 |
self.Bind(wx.EVT_MENU, self.OnTaskBarChangeName, id=self.TBMENU_CHANGE_NAME)
|
|
274 |
self.Bind(wx.EVT_MENU, self.OnTaskBarChangeInterface, id=self.TBMENU_CHANGE_INTERFACE)
|
|
275 |
self.Bind(wx.EVT_MENU, self.OnTaskBarChangePort, id=self.TBMENU_CHANGE_PORT)
|
|
276 |
self.Bind(wx.EVT_MENU, self.OnTaskBarChangeWorkingDir, id=self.TBMENU_CHANGE_WD)
|
|
277 |
self.Bind(wx.EVT_MENU, self.OnTaskBarQuit, id=self.TBMENU_QUIT)
|
|
278 |
|
|
279 |
def CreatePopupMenu(self):
|
|
280 |
"""
|
|
281 |
This method is called by the base class when it needs to popup
|
|
282 |
the menu for the default EVT_RIGHT_DOWN event. Just create
|
|
283 |
the menu how you want it and return it from this function,
|
|
284 |
the base class takes care of the rest.
|
|
285 |
"""
|
|
286 |
menu = wx.Menu()
|
|
287 |
menu.Append(self.TBMENU_CHANGE_NAME, "Change Name")
|
|
288 |
menu.Append(self.TBMENU_CHANGE_INTERFACE, "Change IP of interface to bind")
|
|
289 |
menu.Append(self.TBMENU_CHANGE_PORT, "Change Port Number")
|
|
290 |
menu.AppendSeparator()
|
|
291 |
menu.Append(self.TBMENU_CHANGE_WD, "Change working directory")
|
|
292 |
menu.Append(self.TBMENU_QUIT, "Quit")
|
|
293 |
return menu
|
|
294 |
|
|
295 |
def MakeIcon(self, img):
|
|
296 |
"""
|
|
297 |
The various platforms have different requirements for the
|
|
298 |
icon size...
|
|
299 |
"""
|
|
300 |
if "wxMSW" in wx.PlatformInfo:
|
|
301 |
img = img.Scale(16, 16)
|
|
302 |
elif "wxGTK" in wx.PlatformInfo:
|
|
303 |
img = img.Scale(22, 22)
|
|
304 |
# wxMac can be any size upto 128x128, so leave the source img alone....
|
|
305 |
icon = wx.IconFromBitmap(img.ConvertToBitmap() )
|
|
306 |
return icon
|
|
307 |
|
|
308 |
def OnTaskBarChangeInterface(self,evt):
|
|
309 |
dlg = ParamsEntryDialog(None, "Enter the ip of the interface to bind", defaultValue=pyroserver.ip)
|
|
310 |
dlg.SetTests([(re.compile('\d{1,3}(?:\.\d{1,3}){3}$').match, "Ip is not valid!"),
|
|
311 |
( lambda ip :len([x for x in ip.split(".") if 0 <= int(x) <= 255]) == 4, "Ip is not valid!")
|
|
312 |
])
|
|
313 |
if dlg.ShowModal() == wx.ID_OK:
|
|
314 |
pyroserver.ip = dlg.GetValue()
|
|
315 |
pyroserver.Stop()
|
|
316 |
|
|
317 |
def OnTaskBarChangePort(self,evt):
|
|
318 |
dlg = ParamsEntryDialog(None, "Enter a port number ", defaultValue=str(pyroserver.port))
|
|
319 |
dlg.SetTests([(UnicodeType.isdigit, "Port number must be an integer!"), (lambda port : 0 <= int(port) <= 65535 , "Port number must be 0 <= port <= 65535!")])
|
|
320 |
if dlg.ShowModal() == wx.ID_OK:
|
|
321 |
pyroserver.port = int(dlg.GetValue())
|
|
322 |
pyroserver.Stop()
|
|
323 |
|
|
324 |
|
|
325 |
def OnTaskBarChangeWorkingDir(self,evt):
|
|
326 |
dlg = wx.DirDialog(None, "Choose a working directory ", pyroserver.workdir, wx.DD_NEW_DIR_BUTTON)
|
|
327 |
if dlg.ShowModal() == wx.ID_OK:
|
|
328 |
pyroserver.workdir = dlg.GetPath()
|
|
329 |
pyroserver.Stop()
|
|
330 |
|
|
331 |
def OnTaskBarChangeName(self,evt):
|
|
332 |
dlg = ParamsEntryDialog(None, "Enter a name ", defaultValue=pyroserver.name)
|
|
333 |
dlg.SetTests([(lambda name : len(name) is not 0 , "Name must not be null!")])
|
|
334 |
if dlg.ShowModal() == wx.ID_OK:
|
|
335 |
pyroserver.name = dlg.GetValue()
|
|
336 |
pyroserver.Restart()
|
|
337 |
|
|
338 |
def OnTaskBarQuit(self,evt):
|
|
339 |
pyroserver.Quit()
|
|
340 |
self.RemoveIcon()
|
263
|
341 |
wx.GetApp().ExitMainLoop()
|
262
|
342 |
|
|
343 |
pyroserver = Server(name, ip, port, WorkingDir, args)
|
|
344 |
|
|
345 |
if havewx:
|
|
346 |
app=wx.App(redirect=False)
|
|
347 |
taskbar_instance = DemoTaskBarIcon(pyroserver)
|
|
348 |
pyro_thread=Thread(target=pyroserver.Loop)
|
|
349 |
pyro_thread.start()
|
|
350 |
app.MainLoop()
|
|
351 |
else:
|
|
352 |
pyroserver.Loop()
|