Edouard@1438: import os Edouard@1438: from nevow import rend, appserver, inevow, tags, loaders, athena Edouard@1438: from nevow.page import renderer Edouard@1438: from twisted.python import util Edouard@1438: Edouard@1438: xhtml_header = ''' Edouard@1438: Edouard@1438: ''' Edouard@1438: Edouard@1438: class PLCHMI(athena.LiveElement): Edouard@1438: Edouard@1438: initialised = False Edouard@1438: Edouard@1438: def HMIinitialised(self, result): Edouard@1438: self.initialised = True Edouard@1438: Edouard@1438: def HMIinitialisation(self): Edouard@1438: self.HMIinitialised(None) Edouard@1438: Edouard@1438: class DefaultPLCStartedHMI(PLCHMI): Edouard@1438: docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ Edouard@1438: tags.h1["PLC IS NOW STARTED"], Edouard@1438: ]) Edouard@1438: Edouard@1438: class PLCStoppedHMI(PLCHMI): Edouard@1438: docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ Edouard@1438: tags.h1["PLC IS STOPPED"], Edouard@1438: ]) Edouard@1438: Edouard@1438: class MainPage(athena.LiveElement): Edouard@1438: jsClass = u"WebInterface.PLC" Edouard@1438: docFactory = loaders.stan(tags.div(render=tags.directive('liveElement'))[ Edouard@1438: tags.div(id='content')[ Edouard@1438: tags.div(render = tags.directive('PLCElement')), Edouard@1438: ]]) Edouard@1438: Edouard@1438: def __init__(self, *a, **kw): Edouard@1438: athena.LiveElement.__init__(self, *a, **kw) Edouard@1438: self.pcl_state = False Edouard@1438: self.HMI = None Edouard@1438: self.resetPLCStartedHMI() Edouard@1438: Edouard@1438: def setPLCState(self, state): Edouard@1438: self.pcl_state = state Edouard@1438: if self.HMI is not None: Edouard@1438: self.callRemote('updateHMI') Edouard@1438: Edouard@1438: def setPLCStartedHMI(self, hmi): Edouard@1438: self.PLCStartedHMIClass = hmi Edouard@1438: Edouard@1438: def resetPLCStartedHMI(self): Edouard@1438: self.PLCStartedHMIClass = DefaultPLCStartedHMI Edouard@1438: Edouard@1438: def getHMI(self): Edouard@1438: return self.HMI Edouard@1438: Edouard@1438: def HMIexec(self, function, *args, **kwargs): Edouard@1438: if self.HMI is not None: Edouard@1438: getattr(self.HMI, function, lambda:None)(*args, **kwargs) Edouard@1438: athena.expose(HMIexec) Edouard@1438: Edouard@1438: def resetHMI(self): Edouard@1438: self.HMI = None Edouard@1438: Edouard@1438: def PLCElement(self, ctx, data): Edouard@1438: return self.getPLCElement() Edouard@1438: renderer(PLCElement) Edouard@1438: Edouard@1438: def getPLCElement(self): Edouard@1438: self.detachFragmentChildren() Edouard@1438: if self.pcl_state: Edouard@1438: f = self.PLCStartedHMIClass() Edouard@1438: else: Edouard@1438: f = PLCStoppedHMI() Edouard@1438: f.setFragmentParent(self) Edouard@1438: self.HMI = f Edouard@1438: return f Edouard@1438: athena.expose(getPLCElement) Edouard@1438: Edouard@1438: def detachFragmentChildren(self): Edouard@1438: for child in self.liveFragmentChildren[:]: Edouard@1438: child.detach() Edouard@1438: Edouard@1438: class WebInterface(athena.LivePage): Edouard@1438: Edouard@1438: docFactory = loaders.stan([tags.raw(xhtml_header), Edouard@1438: tags.html(xmlns="http://www.w3.org/1999/xhtml")[ Edouard@1438: tags.head(render=tags.directive('liveglue')), Edouard@1438: tags.body[ Edouard@1438: tags.div[ Edouard@1438: tags.div( render = tags.directive( "MainPage" )) Edouard@1438: ]]]]) Edouard@1438: MainPage = MainPage() Edouard@1438: PLCHMI = PLCHMI Edouard@1438: Edouard@1438: def __init__(self, plcState=False, *a, **kw): Edouard@1438: super(WebInterface, self).__init__(*a, **kw) Edouard@1438: self.jsModules.mapping[u'WebInterface'] = util.sibpath(__file__, 'webinterface.js') Edouard@1438: self.plcState = plcState Edouard@1438: self.MainPage.setPLCState(plcState) Edouard@1438: Edouard@1438: def getHMI(self): Edouard@1438: return self.MainPage.getHMI() Edouard@1438: Edouard@1438: def LoadHMI(self, hmi, jsmodules): Edouard@1438: for name, path in jsmodules.iteritems(): Edouard@1438: self.jsModules.mapping[name] = os.path.join(WorkingDir, path) Edouard@1438: self.MainPage.setPLCStartedHMI(hmi) Edouard@1438: Edouard@1438: def UnLoadHMI(self): Edouard@1438: self.MainPage.resetPLCStartedHMI() Edouard@1438: Edouard@1438: def PLCStarted(self): Edouard@1438: self.plcState = True Edouard@1438: self.MainPage.setPLCState(True) Edouard@1438: Edouard@1438: def PLCStopped(self): Edouard@1438: self.plcState = False Edouard@1438: self.MainPage.setPLCState(False) Edouard@1438: Edouard@1438: def renderHTTP(self, ctx): Edouard@1438: """ Edouard@1438: Force content type to fit with SVG Edouard@1438: """ Edouard@1438: req = inevow.IRequest(ctx) Edouard@1438: req.setHeader('Content-type', 'application/xhtml+xml') Edouard@1438: return super(WebInterface, self).renderHTTP(ctx) Edouard@1438: Edouard@1438: def render_MainPage(self, ctx, data): Edouard@1438: f = self.MainPage Edouard@1438: f.setFragmentParent(self) Edouard@1438: return ctx.tag[f] Edouard@1438: Edouard@1438: def child_(self, ctx): Edouard@1438: self.MainPage.detachFragmentChildren() Edouard@1438: return WebInterface(plcState=self.plcState) Edouard@1438: Edouard@1438: def beforeRender(self, ctx): Edouard@1438: d = self.notifyOnDisconnect() Edouard@1438: d.addErrback(self.disconnected) Edouard@1438: Edouard@1438: def disconnected(self, reason): Edouard@1438: self.MainPage.resetHMI() Edouard@1438: #print reason Edouard@1438: #print "We will be called back when the client disconnects" Edouard@1438: Edouard@1438: def RegisterWebsite(reactor): Edouard@1438: website = WebInterface() Edouard@1438: site = appserver.NevowSite(website) Edouard@1438: Edouard@1438: website_port = 8009 Edouard@1438: website_port_range = 10 Edouard@1438: Edouard@1438: listening = False Edouard@1438: port_offset = 0 Edouard@1438: while not listening and port_offset < website_port_range: Edouard@1438: try: Edouard@1438: reactor.listenTCP(website_port + port_offset, site) Edouard@1438: listening = True Edouard@1438: print "Http interface port :",website_port + port_offset Edouard@1438: return website Edouard@1438: except: # TODO narrow exception Edouard@1438: port_offset += 1 Edouard@1438: Edouard@1438: return None Edouard@1438: Edouard@1438: class statuslistener: Edouard@1438: def __init__(self, site): Edouard@1438: self.oldstate = None Edouard@1438: self.site = site Edouard@1438: Edouard@1438: def listen(self, state): Edouard@1438: if state != self.oldstate: Edouard@1438: {'Started': self.site.PLCStarted, Edouard@1438: 'Stopped': self.site.PLCStopped}[state]() Edouard@1438: self.oldstate = state Edouard@1438: Edouard@1438: def website_statuslistener_factory(site): Edouard@1438: return statuslistener(site).listen