runtime/NevowServer.py
changeset 3803 b3394107eb8b
parent 3800 a5a6ee271e65
child 3804 ef65e5b07464
equal deleted inserted replaced
3802:8616ffd7c29d 3803:b3394107eb8b
    48 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    48 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    49 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    49 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    50 '''
    50 '''
    51 
    51 
    52 WorkingDir = None
    52 WorkingDir = None
    53 
       
    54 
       
    55 class PLCHMI(athena.LiveElement):
       
    56 
       
    57     initialised = False
       
    58 
       
    59     def HMIinitialised(self, result):
       
    60         self.initialised = True
       
    61 
       
    62     def HMIinitialisation(self):
       
    63         self.HMIinitialised(None)
       
    64 
       
    65 
       
    66 class DefaultPLCStartedHMI(PLCHMI):
       
    67     docFactory = loaders.stan(
       
    68         tags.div(render=tags.directive('liveElement'))[
       
    69             tags.h1["PLC IS NOW STARTED"],
       
    70         ])
       
    71 
       
    72 
       
    73 class PLCStoppedHMI(PLCHMI):
       
    74     docFactory = loaders.stan(
       
    75         tags.div(render=tags.directive('liveElement'))[
       
    76             tags.h1["PLC IS STOPPED"],
       
    77         ])
       
    78 
       
    79 
       
    80 class MainPage(athena.LiveElement):
       
    81     jsClass = "WebInterface.PLC"
       
    82     docFactory = loaders.stan(
       
    83         tags.invisible[
       
    84             tags.div(render=tags.directive('liveElement'))[
       
    85                 tags.div(id='content')[
       
    86                     tags.div(render=tags.directive('PLCElement'))]
       
    87             ],
       
    88             tags.a(href='settings')['Settings']])
       
    89 
       
    90     def __init__(self, *a, **kw):
       
    91         athena.LiveElement.__init__(self, *a, **kw)
       
    92         self.pcl_state = False
       
    93         self.HMI = None
       
    94         self.resetPLCStartedHMI()
       
    95 
       
    96     def setPLCState(self, state):
       
    97         self.pcl_state = state
       
    98         if self.HMI is not None:
       
    99             self.callRemote('updateHMI')
       
   100 
       
   101     def setPLCStartedHMI(self, hmi):
       
   102         self.PLCStartedHMIClass = hmi
       
   103 
       
   104     def resetPLCStartedHMI(self):
       
   105         self.PLCStartedHMIClass = DefaultPLCStartedHMI
       
   106 
       
   107     def getHMI(self):
       
   108         return self.HMI
       
   109 
       
   110     def HMIexec(self, function, *args, **kwargs):
       
   111         if self.HMI is not None:
       
   112             getattr(self.HMI, function, lambda: None)(*args, **kwargs)
       
   113     athena.expose(HMIexec)
       
   114 
       
   115     def resetHMI(self):
       
   116         self.HMI = None
       
   117 
       
   118     def PLCElement(self, ctx, data):
       
   119         return self.getPLCElement()
       
   120     renderer(PLCElement)
       
   121 
       
   122     def getPLCElement(self):
       
   123         self.detachFragmentChildren()
       
   124         if self.pcl_state:
       
   125             f = self.PLCStartedHMIClass()
       
   126         else:
       
   127             f = PLCStoppedHMI()
       
   128         f.setFragmentParent(self)
       
   129         self.HMI = f
       
   130         return f
       
   131     athena.expose(getPLCElement)
       
   132 
       
   133     def detachFragmentChildren(self):
       
   134         for child in self.liveFragmentChildren[:]:
       
   135             child.detach()
       
   136 
       
   137 
    53 
   138 class ConfigurableBindings(configurable.Configurable):
    54 class ConfigurableBindings(configurable.Configurable):
   139 
    55 
   140     def __init__(self):
    56     def __init__(self):
   141         configurable.Configurable.__init__(self, None)
    57         configurable.Configurable.__init__(self, None)
   328     def locateChild(self, ctx, segments):
   244     def locateChild(self, ctx, segments):
   329         if segments[0] in customSettingsURLs:
   245         if segments[0] in customSettingsURLs:
   330             return customSettingsURLs[segments[0]](ctx, segments)
   246             return customSettingsURLs[segments[0]](ctx, segments)
   331         return super(SettingsPage, self).locateChild(ctx, segments)
   247         return super(SettingsPage, self).locateChild(ctx, segments)
   332 
   248 
   333 
       
   334 class WebInterface(athena.LivePage):
       
   335 
       
   336     docFactory = loaders.stan([tags.raw(xhtml_header),
       
   337                                tags.html(xmlns="http://www.w3.org/1999/xhtml")[
       
   338                                    tags.head(render=tags.directive('liveglue'))[
       
   339                                        tags.title[PAGE_TITLE],
       
   340                                        tags.link(rel='stylesheet',
       
   341                                                  type='text/css',
       
   342                                                  href=url.here.child("webform_css"))
       
   343                                    ],
       
   344                                    tags.body[
       
   345                                        tags.div[
       
   346                                            tags.div(
       
   347                                                render=tags.directive(
       
   348                                                    "MainPage")),
       
   349                                        ]]]])
       
   350     MainPage = MainPage()
       
   351     PLCHMI = PLCHMI
       
   352 
       
   353     def child_settings(self, context):
       
   354         return SettingsPage()
       
   355 
       
   356     def __init__(self, plcState=False, *a, **kw):
       
   357         super(WebInterface, self).__init__(*a, **kw)
       
   358         self.jsModules.mapping['WebInterface'] = paths.AbsNeighbourFile(
       
   359             __file__, 'webinterface.js')
       
   360         self.plcState = plcState
       
   361         self.MainPage.setPLCState(plcState)
       
   362 
       
   363     def getHMI(self):
       
   364         return self.MainPage.getHMI()
       
   365 
       
   366     def LoadHMI(self, hmi, jsmodules):
       
   367         for name, path in jsmodules.items():
       
   368             self.jsModules.mapping[name] = os.path.join(WorkingDir, path)
       
   369         self.MainPage.setPLCStartedHMI(hmi)
       
   370 
       
   371     def UnLoadHMI(self):
       
   372         self.MainPage.resetPLCStartedHMI()
       
   373 
       
   374     def PLCStarted(self):
       
   375         self.plcState = True
       
   376         self.MainPage.setPLCState(True)
       
   377 
       
   378     def PLCStopped(self):
       
   379         self.plcState = False
       
   380         self.MainPage.setPLCState(False)
       
   381 
       
   382     def renderHTTP(self, ctx):
       
   383         """
       
   384         Force content type to fit with SVG
       
   385         """
       
   386         req = ctx.locate(inevow.IRequest)
       
   387         req.setHeader('Content-type', 'application/xhtml+xml')
       
   388         return super(WebInterface, self).renderHTTP(ctx)
       
   389 
       
   390     def render_MainPage(self, ctx, data):
       
   391         f = self.MainPage
       
   392         f.setFragmentParent(self)
       
   393         return ctx.tag[f]
       
   394 
       
   395     def child_(self, ctx):
       
   396         self.MainPage.detachFragmentChildren()
       
   397         return WebInterface(plcState=self.plcState)
       
   398 
       
   399     def beforeRender(self, ctx):
       
   400         d = self.notifyOnDisconnect()
       
   401         d.addErrback(self.disconnected)
       
   402 
       
   403     def disconnected(self, reason):
       
   404         self.MainPage.resetHMI()
       
   405         # print reason
       
   406         # print "We will be called back when the client disconnects"
       
   407 
       
   408 
       
   409 def RegisterWebsite(iface, port):
   249 def RegisterWebsite(iface, port):
   410     website = WebInterface()
   250     website = SettingsPage()
   411     site = appserver.NevowSite(website)
   251     site = appserver.NevowSite(website)
   412 
   252 
   413     reactor.listenTCP(port, site, interface=iface)
   253     reactor.listenTCP(port, site, interface=iface)
   414     print(_('HTTP interface port :'), port)
   254     print(_('HTTP interface port :'), port)
   415     return website
   255     return website
   416 
       
   417 
       
   418 class statuslistener(object):
       
   419 
       
   420     def __init__(self, site):
       
   421         self.oldstate = None
       
   422         self.site = site
       
   423 
       
   424     def listen(self, state):
       
   425         if state != self.oldstate:
       
   426             action = {'Started': self.site.PLCStarted,
       
   427                       'Stopped': self.site.PLCStopped}.get(state, None)
       
   428             if action is not None:
       
   429                 action()
       
   430             self.oldstate = state
       
   431 
       
   432 
       
   433 def website_statuslistener_factory(site):
       
   434     return statuslistener(site).listen
       
   435 
       
   436