runtime/NevowServer.py
changeset 2225 2a9549e4380e
parent 2219 73042b2d8d65
child 2246 51047284cb0e
child 2266 ed415982a9aa
equal deleted inserted replaced
2188:7f59aa398669 2225:2a9549e4380e
    24 
    24 
    25 
    25 
    26 from __future__ import absolute_import
    26 from __future__ import absolute_import
    27 from __future__ import print_function
    27 from __future__ import print_function
    28 import os
    28 import os
    29 from nevow import appserver, inevow, tags, loaders, athena
    29 import platform
       
    30 from zope.interface import implements
       
    31 from nevow import appserver, inevow, tags, loaders, athena, url, rend
    30 from nevow.page import renderer
    32 from nevow.page import renderer
       
    33 from formless import annotate
       
    34 from formless import webform
       
    35 from formless import configurable
    31 from twisted.internet import reactor
    36 from twisted.internet import reactor
       
    37 
    32 import util.paths as paths
    38 import util.paths as paths
       
    39 from runtime.loglevels import LogLevels, LogLevelsDict
       
    40 
       
    41 PAGE_TITLE = 'Beremiz Runtime Web Interface'
    33 
    42 
    34 xhtml_header = '''<?xml version="1.0" encoding="utf-8"?>
    43 xhtml_header = '''<?xml version="1.0" encoding="utf-8"?>
    35 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    44 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    36 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    45 "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    37 '''
    46 '''
    38 
    47 
    39 WorkingDir = None
    48 WorkingDir = None
       
    49 _PySrv = None
    40 
    50 
    41 
    51 
    42 class PLCHMI(athena.LiveElement):
    52 class PLCHMI(athena.LiveElement):
    43 
    53 
    44     initialised = False
    54     initialised = False
    46     def HMIinitialised(self, result):
    56     def HMIinitialised(self, result):
    47         self.initialised = True
    57         self.initialised = True
    48 
    58 
    49     def HMIinitialisation(self):
    59     def HMIinitialisation(self):
    50         self.HMIinitialised(None)
    60         self.HMIinitialised(None)
    51 
       
    52 
    61 
    53 class DefaultPLCStartedHMI(PLCHMI):
    62 class DefaultPLCStartedHMI(PLCHMI):
    54     docFactory = loaders.stan(
    63     docFactory = loaders.stan(
    55         tags.div(render=tags.directive('liveElement'))[
    64         tags.div(render=tags.directive('liveElement'))[
    56             tags.h1["PLC IS NOW STARTED"],
    65             tags.h1["PLC IS NOW STARTED"],
   117 
   126 
   118     def detachFragmentChildren(self):
   127     def detachFragmentChildren(self):
   119         for child in self.liveFragmentChildren[:]:
   128         for child in self.liveFragmentChildren[:]:
   120             child.detach()
   129             child.detach()
   121 
   130 
       
   131 class ConfigurableBindings(configurable.Configurable):
       
   132 
       
   133     def __init__(self):
       
   134         configurable.Configurable.__init__(self, None)
       
   135         self.bindingsNames = []
       
   136 
       
   137     def getBindingNames(self, ctx):
       
   138         return self.bindingsNames
       
   139 
       
   140     def addExtension(self, name, desc, fields, btnlabel, callback):
       
   141         def _bind(ctx):
       
   142             return annotate.MethodBinding(
       
   143                 'action_'+name,
       
   144                 annotate.Method(arguments=[
       
   145                     annotate.Argument(*field)
       
   146                     for field in fields],
       
   147                     label = desc),
       
   148                 action = btnlabel)
       
   149         setattr(self, 'bind_'+name, _bind)
       
   150             
       
   151         setattr(self, 'action_'+name, callback)
       
   152 
       
   153         self.bindingsNames.append(name)
       
   154 
       
   155 ConfigurableSettings = ConfigurableBindings()
       
   156 
       
   157 class ISettings(annotate.TypedInterface):
       
   158     platform = annotate.String(label = _("Platform"),
       
   159                            default = platform.system() + " " + platform.release(),
       
   160                            immutable = True)
       
   161     # TODO version ?
       
   162 
       
   163     def sendLogMessage(
       
   164         ctx = annotate.Context(),
       
   165         level = annotate.Choice(LogLevels,
       
   166                                 required=True, 
       
   167                                 label=_("Log message level")),
       
   168         message = annotate.String(label=_("Message text"))):
       
   169             pass
       
   170     sendLogMessage = annotate.autocallable(sendLogMessage, 
       
   171                                            label=_("Send a message to the log"),
       
   172                                            action=_("Send"))
       
   173 
       
   174 customSettingsURLs = {
       
   175 }
       
   176 
       
   177 class SettingsPage(rend.Page):
       
   178     # We deserve a slash
       
   179     addSlash = True
       
   180     
       
   181     # This makes webform_css url answer some default CSS
       
   182     child_webform_css = webform.defaultCSS
       
   183 
       
   184     implements(ISettings)
       
   185 
       
   186 
       
   187     docFactory = loaders.stan([tags.html[
       
   188                                    tags.head[
       
   189                                        tags.title[_("Beremiz Runtime Settings")],
       
   190                                        tags.link(rel='stylesheet',
       
   191                                                  type='text/css', 
       
   192                                                  href=url.here.child("webform_css"))
       
   193                                    ],
       
   194                                    tags.body[ 
       
   195                                        tags.h1["Runtime settings:"],
       
   196                                        webform.renderForms('staticSettings'),
       
   197                                        tags.h2["Extensions settings:"],
       
   198                                        webform.renderForms('dynamicSettings'),
       
   199                                    ]]])
       
   200 
       
   201     def configurable_staticSettings(self, ctx):
       
   202         return configurable.TypedInterfaceConfigurable(self)
       
   203 
       
   204     def configurable_dynamicSettings(self, ctx):
       
   205         return ConfigurableSettings
       
   206     
       
   207     def sendLogMessage(self, level, message, **kwargs):
       
   208         level = LogLevelsDict[level]
       
   209         if _PySrv.plcobj is not None:
       
   210             _PySrv.plcobj.LogMessage(level, "Web form log message: " + message )
       
   211 
       
   212     def locateChild(self, ctx, segments):
       
   213         if segments[0] in customSettingsURLs :
       
   214             return customSettingsURLs[segments[0]](ctx, segments)
       
   215         return super(SettingsPage, self).locateChild(ctx, segments)
       
   216 
   122 
   217 
   123 class WebInterface(athena.LivePage):
   218 class WebInterface(athena.LivePage):
   124 
   219 
   125     docFactory = loaders.stan([tags.raw(xhtml_header),
   220     docFactory = loaders.stan([tags.raw(xhtml_header),
   126                                tags.html(xmlns="http://www.w3.org/1999/xhtml")[
   221                                tags.html(xmlns="http://www.w3.org/1999/xhtml")[
   127                                    tags.head(render=tags.directive('liveglue')),
   222                                    tags.head(render=tags.directive('liveglue'))[
       
   223                                        tags.title[PAGE_TITLE],
       
   224                                        tags.link(rel='stylesheet',
       
   225                                                  type='text/css', 
       
   226                                                  href=url.here.child("webform_css"))
       
   227                                    ],
   128                                    tags.body[
   228                                    tags.body[
   129                                        tags.div[
   229                                        tags.div[
   130                                            tags.div(render=tags.directive("MainPage"))
   230                                            tags.div(render=tags.directive("MainPage")),
   131                                        ]]]])
   231                                        ]]]])
   132     MainPage = MainPage()
   232     MainPage = MainPage()
   133     PLCHMI = PLCHMI
   233     PLCHMI = PLCHMI
       
   234 
       
   235     def child_settings(self, context):
       
   236         return SettingsPage()
   134 
   237 
   135     def __init__(self, plcState=False, *a, **kw):
   238     def __init__(self, plcState=False, *a, **kw):
   136         super(WebInterface, self).__init__(*a, **kw)
   239         super(WebInterface, self).__init__(*a, **kw)
   137         self.jsModules.mapping[u'WebInterface'] = paths.AbsNeighbourFile(__file__, 'webinterface.js')
   240         self.jsModules.mapping[u'WebInterface'] = paths.AbsNeighbourFile(__file__, 'webinterface.js')
   138         self.plcState = plcState
   241         self.plcState = plcState
   182         self.MainPage.resetHMI()
   285         self.MainPage.resetHMI()
   183         # print reason
   286         # print reason
   184         # print "We will be called back when the client disconnects"
   287         # print "We will be called back when the client disconnects"
   185 
   288 
   186 
   289 
       
   290 
   187 def RegisterWebsite(port):
   291 def RegisterWebsite(port):
   188     website = WebInterface()
   292     website = WebInterface()
   189     site = appserver.NevowSite(website)
   293     site = appserver.NevowSite(website)
   190 
   294 
   191     reactor.listenTCP(port, site)
   295     reactor.listenTCP(port, site)
   207             self.oldstate = state
   311             self.oldstate = state
   208 
   312 
   209 
   313 
   210 def website_statuslistener_factory(site):
   314 def website_statuslistener_factory(site):
   211     return statuslistener(site).listen
   315     return statuslistener(site).listen
       
   316 
       
   317 
       
   318 def SetServer(pysrv):
       
   319     global _PySrv
       
   320     _PySrv = pysrv
       
   321