class ReportQueue: def __init__(self, rr): self.railroad = rr self.msgQ = queue.Queue(0) self.listener = Listener(self, "192.168.1.142", "8001", self.msgQ) self.listener.start() def serve_forever(self): self.forever = True while self.forever: try: msg = self.msgQ.get(True, 0.25) except queue.Empty: msg = None if msg: #print("(%s)" % msg) jdata = json.loads(msg) if "disconnect" in jdata.keys(): self.forever = False else: self.railroad.processMsg(jdata) self.listener.kill() self.listener.join()
class NodeTester(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, wx.ID_ANY, "Node Tester", size=(500, 500)) self.SetBackgroundColour(wx.Colour(255, 255, 255)) self.Bind(wx.EVT_CLOSE, self.onClose) self.CreateStatusBar() self.qStatus = queue.Queue() menuBar = wx.MenuBar() self.menuServer = wx.Menu() self.menuServer.Append(MENU_SERVER_NODES, "Nodes Report", "Get Nodes Report") self.menuServer.Append(MENU_SERVER_SHUTDOWN, "Shut down", "Shut down server") self.menuNode = wx.Menu() self.menuNode.Append(MENU_NODE_CONFIG, "Re-Config", "Modify current node configuration") self.menuNode.Append(MENU_NODE_INIT, "Init", "Reinit the node communicatione with the server") self.menuWindow = wx.Menu() self.menuWindow.Append(MENU_WINDOW_INPUTS, "Inputs") self.menuWindow.Append(MENU_WINDOW_OUTPUTS, "Outputs") self.menuWindow.Append(MENU_WINDOW_SERVOS, "Servos/Turnouts") menuBar.Append(self.menuServer, "Server") menuBar.Append(self.menuNode, "Node") menuBar.Append(self.menuWindow, "Window") self.Bind(wx.EVT_MENU, self.onMenuNodes, id=MENU_SERVER_NODES) self.Bind(wx.EVT_MENU, self.onMenuShutdown, id=MENU_SERVER_SHUTDOWN) self.Bind(wx.EVT_MENU, self.onMenuConfig, id=MENU_NODE_CONFIG) self.Bind(wx.EVT_MENU, self.onMenuInit, id=MENU_NODE_INIT) self.Bind(wx.EVT_MENU, self.onMenuInputs, id=MENU_WINDOW_INPUTS) self.Bind(wx.EVT_MENU, self.onMenuOutputs, id=MENU_WINDOW_OUTPUTS) self.Bind(wx.EVT_MENU, self.onMenuServos, id=MENU_WINDOW_SERVOS) self.SetMenuBar(menuBar) self.images = Images("images") self.ipAddress = "192.168.1.142" self.httpPort = "8000" self.socketPort = "8001" self.server = Server() self.listener = None self.inputs = 1 self.outputs = 1 self.servos = 1 self.flags = 0 self.registers = 0 self.inputsMap = [] self.outputsMap = [] self.servosMap = [] self.subscribed = False self.currentNodeAddr = None self.timer = wx.Timer(self) self.ticks = 0 self.clearTimer = None sz = wx.BoxSizer(wx.VERTICAL) sz.AddSpacer(2) self.dlgInputs = None self.dlgOutputs = None self.dlgServos = None boxSvr = wx.StaticBox(self, wx.ID_ANY, " Server ") topBorder, botBorder = boxSvr.GetBordersForSizer() if os.name != 'nt': botBorder += 30 bsizer = wx.BoxSizer(wx.VERTICAL) bsizer.AddSpacer(topBorder) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxSvr, wx.ID_ANY, "IP Address:", size=(SVRLABELW, -1))) self.teIpAddr = wx.TextCtrl(boxSvr, wx.ID_ANY, self.ipAddress, size=(125, -1)) self.Bind(wx.EVT_TEXT, self.onTeIpAddrChange, self.teIpAddr) self.teIpAddr.Bind(wx.EVT_KILL_FOCUS, self.onTeIpAddrLoseFocus) self.teIpAddr.Bind(wx.EVT_SET_FOCUS, self.onTeIpAddrSetFocus) hsizer.Add(self.teIpAddr) hsizer.AddSpacer(10) bsizer.Add(hsizer) bsizer.AddSpacer(5) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxSvr, wx.ID_ANY, "HTTP Port:", size=(SVRLABELW, -1))) self.teHPort = wx.TextCtrl(boxSvr, wx.ID_ANY, self.httpPort, size=(125, -1)) self.Bind(wx.EVT_TEXT, self.onTeHPortChange, self.teHPort) self.teHPort.Bind(wx.EVT_KILL_FOCUS, self.onTeHPortLoseFocus) self.teHPort.Bind(wx.EVT_SET_FOCUS, self.onTeHPortSetFocus) hsizer.Add(self.teHPort) hsizer.AddSpacer(10) bsizer.Add(hsizer) bsizer.AddSpacer(5) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxSvr, wx.ID_ANY, "Socket Port:", size=(SVRLABELW, -1))) self.teSPort = wx.TextCtrl(boxSvr, wx.ID_ANY, self.socketPort, size=(125, -1)) hsizer.Add(self.teSPort) hsizer.AddSpacer(10) self.bSubscribe = wx.Button(boxSvr, wx.ID_ANY, "Subscribe") self.bSubscribe.SetToolTip("Subscribe to receive asynchronous reports from the server") self.Bind(wx.EVT_BUTTON, self.onSubscribe, self.bSubscribe) hsizer.Add(self.bSubscribe) hsizer.AddSpacer(10) bsizer.Add(hsizer) bsizer.AddSpacer(botBorder) boxSvr.SetSizer(bsizer) sz.Add(boxSvr, 0, wx.EXPAND|wx.ALL, 5) sz.AddSpacer(10) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(self, wx.ID_ANY, "Node Address:")) hsizer.AddSpacer(10) self.stAddr = wx.StaticText(self, wx.ID_ANY, " ") hsizer.Add(self.stAddr) hsizer.AddSpacer(20) self.bGetAddr = wx.Button(self, wx.ID_ANY, "...", size=(30, -1)) self.bGetAddr.SetToolTip("Select node address") self.Bind(wx.EVT_BUTTON, self.onGetNodeAddr, self.bGetAddr) hsizer.Add(self.bGetAddr) hsizer.AddSpacer(10) self.bRefresh = wx.Button(self, wx.ID_ANY, "Refresh") self.bRefresh.SetToolTip("Refresh node information by querying the actual node") self.Bind(wx.EVT_BUTTON, self.onBRefresh, self.bRefresh) hsizer.Add(self.bRefresh) sz.Add(hsizer) sz.AddSpacer(10) boxCfg = wx.StaticBox(self, wx.ID_ANY, " Node Config ") topBorder, botBorder = boxCfg.GetBordersForSizer() if os.name != 'nt': botBorder += 30 bsizer = wx.BoxSizer(wx.VERTICAL) bsizer.AddSpacer(topBorder) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxCfg, wx.ID_ANY, "Inputs:", size=(CFGLABELW, -1))) self.stInputs = wx.StaticText(boxCfg, wx.ID_ANY, "") hsizer.Add(self.stInputs) hsizer.AddSpacer(10) bsizer.Add(hsizer) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxCfg, wx.ID_ANY, "Outputs:", size=(CFGLABELW, -1))) self.stOutputs = wx.StaticText(boxCfg, wx.ID_ANY, "") hsizer.Add(self.stOutputs) hsizer.AddSpacer(10) bsizer.Add(hsizer) hsizer = wx.BoxSizer(wx.HORIZONTAL) hsizer.AddSpacer(10) hsizer.Add(wx.StaticText(boxCfg, wx.ID_ANY, "Servos:", size=(CFGLABELW, -1))) self.stServos = wx.StaticText(boxCfg, wx.ID_ANY, "") hsizer.Add(self.stServos) hsizer.AddSpacer(10) bsizer.Add(hsizer) bsizer.AddSpacer(botBorder) self.setConfigValues(1, 1, 1) boxCfg.SetSizer(bsizer) sz.Add(boxCfg, 0, wx.EXPAND|wx.ALL, 5) sz.AddSpacer(20) mainsz = wx.BoxSizer(wx.HORIZONTAL) mainsz.AddSpacer(20) mainsz.Add(sz) mainsz.AddSpacer(20) wsz = wx.BoxSizer(wx.VERTICAL) wsz.Add(mainsz) self.SetSizer(wsz) self.Layout() self.Fit() self.Show() self.enableMenuItems(False) self.server.setServerAddress(self.teIpAddr.GetValue(), self.teHPort.GetValue()) self.serverValueChanged = False self.hPortValueChanged = False self.timer.Start(250) self.Bind(wx.EVT_TIMER, self.onTimer) self.Bind(EVT_DELIVERY, self.onDeliveryEvent) self.Bind(EVT_DISCONNECT, self.onDisconnectEvent) self.sz = self.GetSize() print("size = ", self.sz) def onMenuInputs(self, _): if self.currentNodeAddr is None: self.setStatusText("Retrieve configuration first") else: self.openInputsDlg() def openInputsDlg(self): if len(self.inputsMap) == 0: self.setStatusText("No inputs information available") return pos = None if self.dlgInputs is not None: try: pos = self.dlgInputs.GetScreenPosition() self.dlgInputs.Destroy() except: pos = None self.dlgInputs = InputsDlg(self, self.inputsMap, self.inputs, self.currentNodeAddr) if pos is not None: self.dlgInputs.SetPosition(pos) else: ppos = self.GetScreenPosition() self.dlgInputs.SetPosition((ppos[0], ppos[1]+self.sz[1])) self.dlgInputs.Show() self.szInputs = self.dlgInputs.GetSize() def dlgInputsExit(self): self.dlgInputs = None def onMenuOutputs(self, _): if self.currentNodeAddr is None: self.setStatusText("Retrieve configuration first") else: self.openOutputsDlg() def openOutputsDlg(self): if len(self.outputsMap) == 0: self.setStatusText("No outputs information available") return pos = None if self.dlgOutputs is not None: try: pos = self.dlgOutputs.GetScreenPosition() self.dlgOutputs.Destroy() except: pos = None self.dlgOutputs = OutputsDlg(self, self.outputsMap, self.outputs, self.currentNodeAddr) if pos is not None: self.dlgOutputs.SetPosition(pos) else: ppos = self.GetScreenPosition() self.dlgOutputs.SetPosition((ppos[0], ppos[1]+self.sz[1]+self.szInputs[1])) self.dlgOutputs.Show() self.szOutputs = self.GetSize() def dlgOutputsExit(self): self.dlgOutputs = None def onMenuServos(self, _): if self.currentNodeAddr is None: self.setStatusText("Retrieve configuration first") else: self.openServosDlg() def openServosDlg(self): if len(self.servosMap) == 0: self.setStatusText("No outputs information available") return pos = None if self.dlgServos is not None: try: pos = self.dlgServos.GetScreenPosition() self.dlgServos.Destroy() except: pos = None self.dlgServos = ServosDlg(self, self.servosMap, self.servos, self.currentNodeAddr) if pos is not None: self.dlgServos.SetPosition(pos) else: ppos = self.GetScreenPosition() self.dlgServos.SetPosition((ppos[0]+self.sz[0], ppos[1])) self.dlgServos.Show() def dlgServosExit(self): self.dlgServos = None def onTeIpAddrSetFocus(self, evt): self.serverValueChanged = False evt.Skip() def onTeIpAddrChange(self, _): self.serverValueChanged = True def onTeIpAddrLoseFocus(self, evt): if self.serverValueChanged: self.serverValueChanged = False self.server.setServerAddress(self.teIpAddr.GetValue(), self.teHPort.GetValue()) evt.Skip() def onTeHPortSetFocus(self, evt): self.hPortValueChanged = False evt.Skip() def onTeHPortChange(self, _): self.hPortValueChanged = True def onTeHPortLoseFocus(self, evt): if self.hPortValueChanged: self.hPortValueChanged = False self.server.setServerAddress(self.teIpAddr.GetValue(), self.teHPort.GetValue()) evt.Skip() def throwTurnout(self, tx, throw): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr if throw == "N": try: sc, data = self.server.setTurnoutNormal(addr, tx) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False elif throw == "R": try: sc, data = self.server.setTurnoutReverse(addr, tx) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False else: # throw == "T" try: sc, data = self.server.setTurnoutToggle(addr, tx) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: if throw == "N": self.servosMap[tx][3] = self.servosMap[tx][0] elif throw == "R": self.servosMap[tx][3] = self.servosMap[tx][1] else: if self.servosMap[tx][3] == self.servosMap[tx][0]: self.servosMap[tx][3] = self.servosMap[tx][1] if self.servosMap[tx][3] == self.servosMap[tx][1]: self.servosMap[tx][3] = self.servosMap[tx][0] else: # toggle would have done nothing here pass self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def setServoAngle(self, sx, ang): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr try: sc, data = self.server.setServoAngle(addr, sx, ang) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: self.servosMap[sx][3] = ang self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def setTurnoutLimits(self, tx, norm, rev, ini): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr try: sc, data = self.server.setlimits(addr, tx, norm, rev, ini) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: self.servosMap[tx][0] = norm self.servosMap[tx][1] = rev self.servosMap[tx][2] = ini self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def swapTurnout(self, tx): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr sv = self.servosMap[tx] norm = sv[0] rev = sv[1] try: sc, data = self.server.setlimits(addr, tx, rev, norm, sv[2]) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: self.servosMap[tx][0] = rev self.servosMap[tx][1] = norm self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def nodeStore(self): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr try: sc, data = self.server.nodeStore(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: self.setStatusText("Success") return True else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def getServosMap(self): return self.servosMap def setOutput(self, bn, newState): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr if newState: try: sc, data = self.server.setOutputOn(addr, bn) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False else: try: sc, data = self.server.setOutputOff(addr, bn) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: self.outputsMap[bn] = newState self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def pulseOutput(self, bn, pl): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr try: sc, data = self.server.pulseOutput(addr, bn, pl) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: try: self.setStatusText("Success") return True except: self.setStatusText("Unable to process return data: '%s'" % data) return False else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def setConfigValues(self, i, o, s): self.inputs = i self.stInputs.SetLabel("%d" % i) self.outputs = o self.stOutputs.SetLabel("%d" % o) self.servos = s self.stServos.SetLabel("%d" % s) def onSubscribe(self, _): if self.subscribed: self.listener.kill() self.listener.join() self.listener = None self.subscribed = False self.bSubscribe.SetLabel("Subscribe") else: ip = self.teIpAddr.GetValue() pt = self.teSPort.GetValue() self.listener = Listener(self, ip, pt) self.listener.start() self.subscribed = True self.bSubscribe.SetLabel("Unsubscribe") def raiseDeliveryEvent(self, data): try: jdata = json.loads(data) except json.decoder.JSONDecodeError: print("Unable to parse (%s)" % data) return evt = DeliveryEvent(data=jdata) wx.PostEvent(self, evt) def raiseDisconnectEvent(self): evt = DisconnectEvent() wx.PostEvent(self, evt) def onDisconnectEvent(self, _): self.listener = None self.subscribed = False self.bSubscribe.SetLabel("Subscribe") self.setStatusText("Server socket closed") def setStatusText(self, text): if self.clearTimer == 0: self.clearTimer = 10 self.SetStatusText(text) else: self.qStatus.put(text) def onGetNodeAddr(self, _): nr = self.getNodeRpt() if nr is None: dlg = wx.MessageDialog(self, 'Unable to retrieve node report from server', 'Error', wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return dlg = NodeDlg(self, self.currentNodeAddr, nr) rc = dlg.ShowModal() if rc in [ wx.ID_OK, ID_INIT ]: n = dlg.getValues() dlg.Destroy() if rc not in [ wx.ID_OK, ID_INIT ]: return if n is None: return if rc == wx.ID_OK: self.currentNodeAddr = n self.stAddr.SetLabel("%d" % self.currentNodeAddr) self.loadConfig() else: self.doInit(n) def onBRefresh(self, _): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr try: sc, data = self.server.nodeRefresh(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return if sc >= 400: self.setStatusText("RC <%d> %s" % (sc, data)) return False self.setStatusText("Refresh Success") self.loadConfig() def loadConfig(self): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() addr = self.currentNodeAddr if addr is None: self.setStatusText("Select node address first") self.enableMenuItems(False) self.enableMenuItems(True) try: sc, data = self.server.getConfig(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) if sc < 400: try: d = json.loads(data) self.setConfigValues(d['inputs'], d['outputs'], d['servos']) self.setStatusText("Retrieve Node Config Success") except: self.setStatusText("Unable to process return data: '%s'" % data) else: self.setStatusText("RC <%d> %s" % (sc, data)) try: sc, data = self.server.getInputs(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return if sc < 400: try: d = json.loads(data) self.inputsMap = d["inputs"]["values"] self.openInputsDlg() self.setStatusText("Retrieve Inputs Success") except: self.inputsMap = [] self.setStatusText("Unable to process return data: '%s'" % data) else: self.setStatusText("RC <%d> %s" % (sc, data)) try: sc, data = self.server.getOutputs(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return if sc < 400: try: d = json.loads(data) self.outputsMap = d["outputs"]["values"] self.openOutputsDlg() self.setStatusText("Retrieve Outputs Success") except: self.outputsMap = [] self.setStatusText("Unable to process return data: '%s'" % data) else: self.setStatusText("RC <%d> %s" % (sc, data)) try: sc, data = self.server.getTurnouts(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return if sc < 400: try: d = json.loads(data) self.servosMap = d["servos"]["values"] self.openServosDlg() self.setStatusText("Retrieve Turnouts Success") except: self.servosMap = [] self.setStatusText("Unable to process return data: '%s'" % data) else: self.setStatusText("RC <%d> %s" % (sc, data)) def enableMenuItems(self, flag): self.menuNode.Enable(MENU_NODE_CONFIG, flag) self.menuWindow.Enable(MENU_WINDOW_INPUTS, flag) self.menuWindow.Enable(MENU_WINDOW_OUTPUTS, flag) self.menuWindow.Enable(MENU_WINDOW_SERVOS, flag) self.bRefresh.Enable(flag) def onDeliveryEvent(self, evt): if "inputs" in evt.data: imsg = evt.data["inputs"] iaddr = imsg["address"] if iaddr != self.currentNodeAddr: return if "delta" in imsg and imsg["delta"]: vals = imsg["values"] if len(vals) > 0: for inp, val in vals: self.inputsMap[inp] = val if self.dlgInputs is not None: self.dlgInputs.update(self.inputsMap) else: vals = imsg["values"] if len(vals) == len(self.inputsMap): self.inputsMap = [x for x in vals] if self.dlgInputs is not None: self.dlgInputs.update(self.inputsMap) else: self.setStatusText("Mismatch number of inputs") elif "outputs" in evt.data: omsg = evt.data["outputs"] iaddr = omsg["address"] if iaddr != self.currentNodeAddr: return if "delta" in omsg and omsg["delta"]: vals = omsg["values"] if len(vals) > 0: for outp, val in vals: self.outputsMap[outp] = val if self.dlgOutputs is not None: self.dlgOutputs.update(self.outputsMap) else: vals = omsg["values"] if len(vals) == len(self.outputsMap): self.outputsMap = [x for x in vals] if self.dlgOutputs is not None: self.dlgOutputs.update(self.outputsMap) else: self.setStatusText("Mismatch number of outputs") elif "servos" in evt.data: smsg = evt.data["servos"] iaddr = smsg["address"] if iaddr != self.currentNodeAddr: return if "limits" in smsg and smsg["limits"]: vals = smsg["values"] if len(vals) > 0: for outp, v0, v1, v2 in vals: self.servosMap[outp][0] = v0 self.servosMap[outp][1] = v1 self.servosMap[outp][2] = v2 if self.dlgServos is not None: self.dlgServos.update(self.servosMap) elif "delta" in smsg and smsg["delta"]: vals = smsg["values"] if len(vals) > 0: for outp, val in vals: self.servosMap[outp][3] = val if self.dlgServos is not None: self.dlgServos.update(self.servosMap) else: vals = smsg["values"] if len(vals) == len(self.servosMap): self.servosMap = [x for x in vals] if self.dlgServos is not None: self.dlgServos.update(self.servosMap) else: self.setStatusText("Mismatch number of turnouts/servos") elif "pulse" in evt.data: pmsg = evt.data["pulse"] iaddr = pmsg["address"] if iaddr != self.currentNodeAddr: return idx = pmsg["index"] pl = pmsg["length"] self.outputsMap[idx] = False # only on for a brief period if self.dlgOutputs is not None: self.dlgOutputs.pulseOutput(idx, pl) elif "nodes" in evt.data: print(json.dumps(evt.data)) if self.currentNodeAddr is None: # nothing to do with this is we are not currently looking at a node return for nd in evt.data["nodes"]: if nd["address"] == self.currentNodeAddr and not nd["active"]: # we are looking at an inactive node - tear down the dialog boxes if self.dlgInputs is not None: self.dlgInputs.Destroy() self.dlgInputs = None if self.dlgOutputs is not None: self.dlgOutputs.Destroy() self.dlgOutputs = None if self.dlgServos is not None: self.dlgServos.Destroy() self.dlgServos = None self.currentNodeAddr = None self.stAddr.SetLabel(" ") break else: print("Unknown report type (%s)" % list(evt.data.keys())[0]) def onMessageEvent(self, evt): self.setStatusText(evt.message) def getNodeRpt(self): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() try: sc, data = self.server.getNodeRpt() except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return None if sc < 400: try: self.setStatusText("Success") d = json.loads(data) return d except: self.setStatusText("Unable to process return data: '%s'" % data) return None else: self.setStatusText("RC <%d> %s" % (sc, data)) return None def onMenuNodes(self, _): d = self.getNodeRpt() if d is None: return False try: nl = d["nodes"] except: return False rpt = "" for nd in nl: active = "Active" if nd["active"] else "Inactive" rpt += "%20.20s: A:%-2d I:%-2d O:%-2d S:%-2d %s\n" % ( nd["name"], nd["address"], nd["inputs"], nd["outputs"], nd["servos"], active) dlg = wx.MessageDialog(self, rpt, "Nodes Report", wx.OK | wx.ICON_INFORMATION) dlg.ShowModal() dlg.Destroy() return True def onMenuConfig(self, _): addr = self.currentNodeAddr dlg = wx.MessageDialog(self, "Proceeding with this will result in the node restarting\nand will require a reconfiguration and restart of the server process", "Reconfiguration of Node %d" % addr, wx.OK | wx.CANCEL | wx.ICON_WARNING) rc = dlg.ShowModal() dlg.Destroy() if rc == wx.ID_OK: dlg = NodeConfigDlg(self, addr, self.inputs, self.outputs, self.servos) rc = dlg.ShowModal() if rc == wx.ID_OK: a, i, o, s = dlg.getValues() dlg.Destroy() if rc != wx.ID_OK: return ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() try: sc, data = self.server.setConfig(addr, a, i, o, s) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: self.setStatusText("Success") return True else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def onMenuInit(self, _): if self.currentNodeAddr is None: return self.doInit(self.currentNodeAddr) def doInit(self, addr): ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() try: sc, data = self.server.nodeInit(addr) except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: self.setStatusText("Success") return True else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def onMenuShutdown(self, _): dlg = wx.MessageDialog(self, "This will shutdown the server process.\nAre you sure you want to proceed?", "Continue with server shutdown", wx.YES_NO | wx.NO_DEFAULT | wx.ICON_WARNING) rc = dlg.ShowModal() dlg.Destroy() if rc == wx.ID_YES: ip = self.teIpAddr.GetValue() pt = self.teHPort.GetValue() try: sc, data = self.server.quit() except: self.setStatusText("Unable to connect to node server at address %s:%s" % (ip, pt)) return False if sc < 400: self.setStatusText("Success") return True else: self.setStatusText("RC <%d> %s" % (sc, data)) return False def onTimer(self, _): # do this every quarter second if self.dlgOutputs is not None: self.dlgOutputs.clearPulses() self.ticks += 1 if self.ticks < 4: return self.ticks = 0 # do this once a second if self.clearTimer is None: return if self.clearTimer == 0: if self.qStatus.empty(): self.SetStatusText("") self.clearTimer = None else: t = self.qStatus.get() self.SetStatusText(t) elif self.clearTimer >0: self.clearTimer -= 1 def onClose(self, _): if self.listener is not None: self.setStatusText("destroying listener thread") self.listener.kill() self.listener.join() self.Destroy()
#!/usr/bin/env python # -*- coding: utf-8 -*- import sys import logging.config from config import config from listener import Listener logging.filename = 'logs/{}_log'.format(config['server_name']) logging.config.fileConfig('logging.ini') if __name__ == '__main__': if '-h' in sys.argv or '--help' in sys.argv: print('Run this file and as the first argument send name of the config' 'file. For example: python main.py config.ini') if len(sys.argv) < 2: logging.error('Please specify config name.') sys.exit(1) listener = Listener() try: listener.start() except KeyboardInterrupt: logging.info('KeyboardInterrupt. Exiting...') listener.stop() listener.join()
class NetMgr(Mgr): def __init__(self, engine,localOptions): Mgr.__init__(self, engine) self.engine = engine self.networkingEnabled = localOptions.enableNetworking if self.networkingEnabled: self.server = localOptions.server else: self.server = False self.ip = localOptions.ip self.remainingIDs = [] self.timeToWaitForPlayers = 10 def initialize(self): pass def loadLevel(self): if self.networkingEnabled: self.broadcaster = Broadcaster() self.listener = Listener() self.listener.start() self.broadcaster.start() if self.server or not self.networkingEnabled: self.remainingIDs.append([1,""]) self.remainingIDs.append([2,""]) def releaseLevel(self): if self.networkingEnabled: self.listener.stop() self.broadcaster.stop() self.listener.join() self.broadcaster.join() def tick(self, dtime): if self.networkingEnabled: if dtime < 1 and self.timeToWaitForPlayers > 0: self.timeToWaitForPlayers -= dtime # check to see if all players are ready to start the race if self.timeToWaitForPlayers > 0 and self.engine.gameMgr.allPlayersReady == False: allReady = True for ent in self.engine.entMgr.entities: if not ent.isReady: allReady = False if len(self.engine.entMgr.entities) > 1: self.engine.gameMgr.allPlayersReady = allReady elif self.timeToWaitForPlayers <= 0: self.engine.gameMgr.allPlayersReady = True # get messages incoming = self.listener.getMessages() outgoingMsgs = [] for msgs in incoming: msgType, msg = messages.unpack(msgs) if msgType == const.STATUS: found = False # check to see if the status message is regarding a ship that is already created for ent in self.engine.entMgr.entities: if ent.shipId == msg.shipId: found = True # if it is, send updates to entity if found and msg.shipId != self.engine.entMgr.playerIndex: self.engine.entMgr.entities[msg.shipId].updateQueue.append(msg) # if it isn't, create that entity elif not found: ent = Spaceship("Ship" + str(msg.shipId),msg.shipId, self.engine,const.MESHES[msg.shipId]) ent.pos = self.engine.entMgr.nextPos self.engine.entMgr.nextPos.x += 40 self.engine.entMgr.entities.append(ent) # only process requests before game has started elif msgType == const.REQUEST and self.timeToWaitForPlayers > 0: for ID in self.remainingIDs: # if the id has not been issued already, or if the ID corresponds to a user who has been given an ID (but did not recieve their ID), send the ID if ID[1] == "" or ID[1] == msg.userName: outgoingMsgs.append(messages.pack(messages.InfoMessage(msg.userName,ID[0]),const.INFO)) ID[1] = msg.userName # only process info messages when this player has not been handed a playerIndex elif msgType == const.INFO and not self.server and self.engine.entMgr.playerIndex == -1: self.engine.entMgr.playerIndex = msg.shipId found = False for ent in self.engine.entMgr.entities: if ent.shipId == msg.shipId: found = True if not found: ent = Spaceship("Ship" + str(msg.shipId),msg.shipId, self.engine,const.MESHES[msg.shipId]) ent.pos = self.engine.entMgr.nextPos self.engine.entMgr.nextPos.x += 40 self.engine.entMgr.entities.append(ent) # if this player has not been handed a playerIndex, request one. if self.engine.entMgr.playerIndex == -1: outgoingMsgs.append(messages.pack(messages.RequestMessage(str(socket.gethostname())),const.REQUEST)) # if the player has been handed a playerIndex, send the status of your ship else: myId = self.engine.entMgr.playerIndex myEnt = self.engine.entMgr.entities[myId] outgoingMsgs.append(messages.pack(messages.StatusMessage(myId,myEnt.pos,myEnt.dir,myEnt.colVel,myEnt.speed,myEnt.pitch, myEnt.roll,myEnt.isReady),const.STATUS)) # send outgoing messages for msg in outgoingMsgs: self.broadcaster.addMessage(msg)