241 # The configuration of the web form used to see/edit the BACnet parameters |
241 # The configuration of the web form used to see/edit the BACnet parameters |
242 webFormInterface = [(name, web_dtype (label=web_label, default=_GetWebviewConfigurationValue)) |
242 webFormInterface = [(name, web_dtype (label=web_label, default=_GetWebviewConfigurationValue)) |
243 for name, web_label, c_dtype, web_dtype in BACnet_parameters] |
243 for name, web_label, c_dtype, web_dtype in BACnet_parameters] |
244 |
244 |
245 |
245 |
246 |
|
247 def _updateWebInterface(): |
|
248 """ |
|
249 # Add/Remove buttons to/from the web interface depending on the current state |
|
250 # |
|
251 # - If there is a saved state => add a delete saved state button |
|
252 """ |
|
253 |
|
254 # Add a "Delete Saved Configuration" button if there is a saved configuration! |
|
255 if _SavedConfiguration is None: |
|
256 NS.ConfigurableSettings.delSettings("BACnetConfigDelSaved") |
|
257 else: |
|
258 NS.ConfigurableSettings.addSettings( |
|
259 "BACnetConfigDelSaved", # name |
|
260 _("BACnet Configuration"), # description |
|
261 [], # fields (empty, no parameters required!) |
|
262 _("Delete Configuration Stored in Persistent Storage"), # button label |
|
263 OnButtonDel, # callback |
|
264 "BACnetConfigParm") # Add after entry xxxx |
|
265 |
|
266 |
|
267 def OnButtonSave(**kwargs): |
246 def OnButtonSave(**kwargs): |
268 """ |
247 """ |
269 # Function called when user clicks 'Save' button in web interface |
248 # Function called when user clicks 'Save' button in web interface |
270 # The function will configure the BACnet plugin in the PLC with the values |
249 # The function will configure the BACnet plugin in the PLC with the values |
271 # specified in the web interface. However, values must be validated first! |
250 # specified in the web interface. However, values must be validated first! |
277 for par_name, x1, x2, x3 in BACnet_parameters: |
256 for par_name, x1, x2, x3 in BACnet_parameters: |
278 value = kwargs.get(par_name, None) |
257 value = kwargs.get(par_name, None) |
279 if value is not None: |
258 if value is not None: |
280 newConfig[par_name] = value |
259 newConfig[par_name] = value |
281 |
260 |
282 global _WebviewConfiguration |
|
283 _WebviewConfiguration = newConfig |
|
284 |
261 |
285 # First check if configuration is OK. |
262 # First check if configuration is OK. |
286 if not _CheckWebConfiguration(newConfig): |
263 if not _CheckWebConfiguration(newConfig): |
287 return |
264 return |
288 |
265 |
292 _SetSavedConfiguration(newConfig) |
269 _SetSavedConfiguration(newConfig) |
293 |
270 |
294 # Configure PLC with the current BACnet parameters |
271 # Configure PLC with the current BACnet parameters |
295 _SetPLCConfiguration(newConfig) |
272 _SetPLCConfiguration(newConfig) |
296 |
273 |
297 # File has just been created => Delete button must be shown on web interface! |
274 |
298 _updateWebInterface() |
275 |
299 |
276 def OnButtonReset(**kwargs): |
300 |
|
301 |
|
302 |
|
303 def OnButtonDel(**kwargs): |
|
304 """ |
277 """ |
305 # Function called when user clicks 'Delete' button in web interface |
278 # Function called when user clicks 'Delete' button in web interface |
306 # The function will delete the file containing the persistent |
279 # The function will delete the file containing the persistent |
307 # BACnet configution |
280 # BACnet configution |
308 """ |
281 """ |
312 # Set the current configuration to the default (hardcoded in C) |
285 # Set the current configuration to the default (hardcoded in C) |
313 _SetPLCConfiguration(_DefaultConfiguration) |
286 _SetPLCConfiguration(_DefaultConfiguration) |
314 # Reset global variable |
287 # Reset global variable |
315 global _SavedConfiguration |
288 global _SavedConfiguration |
316 _SavedConfiguration = None |
289 _SavedConfiguration = None |
317 # File has just been deleted => Delete button on web interface no longer needed! |
290 |
318 _updateWebInterface() |
291 |
319 |
292 |
320 |
293 # location_str is replaced by extension's value in CTNGenerateC call |
321 |
|
322 def OnButtonShowCur(**kwargs): |
|
323 """ |
|
324 # Function called when user clicks 'Show Current PLC Configuration' button in web interface |
|
325 # The function will load the current PLC configuration into the web form |
|
326 """ |
|
327 |
|
328 global _WebviewConfiguration |
|
329 _WebviewConfiguration = _GetPLCConfiguration() |
|
330 # File has just been deleted => Delete button on web interface no longer needed! |
|
331 _updateWebInterface() |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 def _runtime_bacnet_websettings_%(location_str)s_init(): |
294 def _runtime_bacnet_websettings_%(location_str)s_init(): |
337 """ |
295 """ |
338 # Callback function, called (by PLCObject.py) when a new PLC program |
296 # Callback function, called (by PLCObject.py) when a new PLC program |
339 # (i.e. XXX.so file) is transfered to the PLC runtime |
297 # (i.e. XXX.so file) is transfered to the PLC runtime |
340 # and oaded into memory |
298 # and oaded into memory |
344 |
302 |
345 if PLCObject.PLClibraryHandle is None: |
303 if PLCObject.PLClibraryHandle is None: |
346 # PLC was loaded but we don't have access to the library of compiled code (.so lib)? |
304 # PLC was loaded but we don't have access to the library of compiled code (.so lib)? |
347 # Hmm... This shold never occur!! |
305 # Hmm... This shold never occur!! |
348 return |
306 return |
349 |
|
350 # Get the location (in the Config. Node Tree of Beremiz IDE) the BACnet plugin |
|
351 # occupies in the currently loaded PLC project (i.e., the .so file) |
|
352 # If the "__bacnet_plugin_location" C variable is not present in the .so file, |
|
353 # we conclude that the currently loaded PLC does not have the BACnet plugin |
|
354 # included (situation (2b) described above init()) |
|
355 try: |
|
356 location = ctypes.c_char_p.in_dll(PLCObject.PLClibraryHandle, "__bacnet_plugin_location") |
|
357 except Exception: |
|
358 # Loaded PLC does not have the BACnet plugin => nothing to do |
|
359 # (i.e. do _not_ configure and make available the BACnet web interface) |
|
360 return |
|
361 |
307 |
362 # Map the get/set functions (written in C code) we will be using to get/set the configuration parameters |
308 # Map the get/set functions (written in C code) we will be using to get/set the configuration parameters |
363 for name, web_label, c_dtype, web_dtype in BACnet_parameters: |
309 for name, web_label, c_dtype, web_dtype in BACnet_parameters: |
364 GetParamFuncName = "__bacnet_" + location.value + "_get_ConfigParam_" + name |
310 # location_str is replaced by extension's value in CTNGenerateC call |
365 SetParamFuncName = "__bacnet_" + location.value + "_set_ConfigParam_" + name |
311 GetParamFuncName = "__bacnet_%(location_str)s_get_ConfigParam_" + name |
|
312 SetParamFuncName = "__bacnet_%(location_str)s_set_ConfigParam_" + name |
366 |
313 |
367 GetParamFuncs[name] = getattr(PLCObject.PLClibraryHandle, GetParamFuncName) |
314 GetParamFuncs[name] = getattr(PLCObject.PLClibraryHandle, GetParamFuncName) |
368 GetParamFuncs[name].restype = c_dtype |
315 GetParamFuncs[name].restype = c_dtype |
369 GetParamFuncs[name].argtypes = None |
316 GetParamFuncs[name].argtypes = None |
370 |
317 |
397 _SavedConfiguration = _GetSavedConfiguration() |
344 _SavedConfiguration = _GetSavedConfiguration() |
398 if _SavedConfiguration is not None: |
345 if _SavedConfiguration is not None: |
399 if _CheckConfiguration(_SavedConfiguration): |
346 if _CheckConfiguration(_SavedConfiguration): |
400 _SetPLCConfiguration(_SavedConfiguration) |
347 _SetPLCConfiguration(_SavedConfiguration) |
401 |
348 |
|
349 WebSettings = NS.newExtensionSetting("BACnet") |
|
350 |
402 # Configure the web interface to include the BACnet config parameters |
351 # Configure the web interface to include the BACnet config parameters |
403 NS.ConfigurableSettings.addSettings( |
352 WebSettings.addSettings( |
404 "BACnetConfigParm", # name |
353 "BACnetConfigParm", # name |
405 _("BACnet Configuration"), # description |
354 _("BACnet Configuration"), # description |
406 webFormInterface, # fields |
355 webFormInterface, # fields |
407 _("Save Configuration to Persistent Storage"), # button label |
356 _("Apply"), # button label |
408 OnButtonSave) # callback |
357 OnButtonSave) # callback |
409 |
358 |
410 # Add a "View Current Configuration" button |
359 # Add the Delete button to the web interface |
411 NS.ConfigurableSettings.addSettings( |
360 WebSettings.addSettings( |
412 "BACnetConfigViewCur", # name |
361 "BACnetConfigDelSaved", # name |
413 _("BACnet Configuration"), # description |
362 _("BACnet Configuration"), # description |
414 [], # fields (empty, no parameters required!) |
363 [ ("status", |
415 _("Show Current PLC Configuration"), # button label |
364 annotate.String(label=_("Current state"), |
416 OnButtonShowCur) # callback |
365 immutable=True, |
417 |
366 default=lambda *k:getConfigStatus())), |
418 # Add the Delete button to the web interface, if required |
367 ], # fields (empty, no parameters required!) |
419 _updateWebInterface() |
368 _("Reset"), # button label |
420 |
369 OnButtonReset) |
421 |
370 |
422 |
371 |
423 |
372 |
424 |
373 def getConfigStatus(): |
|
374 if _WebviewConfiguration == _DefaultConfiguration : |
|
375 return "Unchanged" |
|
376 return "Modified" |
|
377 |
|
378 |
|
379 # location_str is replaced by extension's value in CTNGenerateC call |
425 def _runtime_bacnet_websettings_%(location_str)s_cleanup(): |
380 def _runtime_bacnet_websettings_%(location_str)s_cleanup(): |
426 """ |
381 """ |
427 # Callback function, called (by PLCObject.py) when a PLC program is unloaded from memory |
382 # Callback function, called (by PLCObject.py) when a PLC program is unloaded from memory |
428 """ |
383 """ |
429 |
384 |
430 #PLCObject.LogMessage("BACnet web server extension::OnUnLoadPLC() Called...") |
385 #PLCObject.LogMessage("BACnet web server extension::OnUnLoadPLC() Called...") |
431 |
386 |
432 # Delete the BACnet specific web interface extensions |
387 NS.removeExtensionSetting("BACnet") |
433 # (Safe to ask to delete, even if it has not been added!) |
388 |
434 NS.ConfigurableSettings.delSettings("BACnetConfigParm") |
|
435 NS.ConfigurableSettings.delSettings("BACnetConfigViewCur") |
|
436 NS.ConfigurableSettings.delSettings("BACnetConfigDelSaved") |
|
437 GetParamFuncs = {} |
389 GetParamFuncs = {} |
438 SetParamFuncs = {} |
390 SetParamFuncs = {} |
439 _WebviewConfiguration = None |
391 _WebviewConfiguration = None |
440 _SavedConfiguration = None |
392 _SavedConfiguration = None |
441 |
393 |