--- a/ConfigTreeNode.py Tue Jun 16 11:12:36 2020 +0200
+++ b/ConfigTreeNode.py Tue Jun 16 15:53:52 2020 +0200
@@ -678,6 +678,3 @@
raise UserAddressedException(message)
-class UserAddressedException(Exception):
- pass
-
--- a/POULibrary.py Tue Jun 16 11:12:36 2020 +0200
+++ b/POULibrary.py Tue Jun 16 15:53:52 2020 +0200
@@ -26,6 +26,10 @@
from __future__ import absolute_import
from weakref import ref
+# Exception type for problems that user has to take action in order to fix
+class UserAddressedException(Exception):
+ pass
+
class POULibrary(object):
def __init__(self, CTR, LibName, TypeStack):
@@ -59,6 +63,11 @@
# Pure python or IEC libs doesn't produce C code
return ((""), [], False), ""
+ def FatalError(self, message):
+ """ Raise an exception that will trigger error message intended to
+ the user, but without backtrace since it is not a software error """
+
+ raise UserAddressedException(message)
def SimplePOULibraryFactory(path):
class SimplePOULibrary(POULibrary):
--- a/ProjectController.py Tue Jun 16 11:12:36 2020 +0200
+++ b/ProjectController.py Tue Jun 16 15:53:52 2020 +0200
@@ -63,7 +63,8 @@
import targets
from runtime.typemapping import DebugTypesSize, UnpackDebugBuffer
from runtime import PlcStatus
-from ConfigTreeNode import ConfigTreeNode, XSDSchemaErrorMessage, UserAddressedException
+from ConfigTreeNode import ConfigTreeNode, XSDSchemaErrorMessage
+from POULibrary import UserAddressedException
base_folder = paths.AbsParentDir(__file__)
@@ -1441,7 +1442,8 @@
PlcStatus.Stopped: {"_Run": True,
"_Transfer": True,
"_Connect": False,
- "_Disconnect": True},
+ "_Disconnect": True,
+ "_Repair": True},
PlcStatus.Empty: {"_Transfer": True,
"_Connect": False,
"_Disconnect": True},
@@ -1978,6 +1980,13 @@
"shown": False,
},
{
+ "bitmap": "Disconnect",
+ "name": _("Disconnect"),
+ "tooltip": _("Disconnect from PLC"),
+ "method": "_Disconnect",
+ "shown": False,
+ },
+ {
"bitmap": "Repair",
"name": _("Repair"),
"tooltip": _("Repair broken PLC"),
@@ -1985,13 +1994,6 @@
"shown": False,
},
{
- "bitmap": "Disconnect",
- "name": _("Disconnect"),
- "tooltip": _("Disconnect from PLC"),
- "method": "_Disconnect",
- "shown": False,
- },
- {
"bitmap": "IDManager",
"name": _("ID Manager"),
"tooltip": _("Manage secure connection identities"),
--- a/runtime/PLCObject.py Tue Jun 16 11:12:36 2020 +0200
+++ b/runtime/PLCObject.py Tue Jun 16 15:53:52 2020 +0200
@@ -451,17 +451,27 @@
self.PythonThreadCond.notify()
self.PythonThreadCondLock.release()
+ def _fail(msg):
+ self.LogMessage(0, msg)
+ self.PLCStatus = PlcStatus.Broken
+ self.StatusChange()
+
+ def PreStartPLC(self):
+ """
+ Here goes actions to be taken just before PLC starts,
+ with all libraries and python object already created.
+ For example : restore saved proprietary parameters
+ """
+ pass
+
@RunInMain
def StartPLC(self):
- def fail(msg):
- self.LogMessage(0, msg)
- self.PLCStatus = PlcStatus.Broken
- self.StatusChange()
-
if self.PLClibraryHandle is None:
if not self.LoadPLC():
- fail(_("Problem starting PLC : can't load PLC"))
+ self._fail(_("Problem starting PLC : can't load PLC"))
+
+ self.PreStartPLC()
if self.CurrentPLCFilename is not None and self.PLCStatus == PlcStatus.Stopped:
c_argv = ctypes.c_char_p * len(self.argv)
@@ -472,7 +482,7 @@
self.PythonThreadCommand("Activate")
self.LogMessage("PLC started")
else:
- fail(_("Problem starting PLC : error %d" % res))
+ self._fail(_("Problem starting PLC : error %d" % res))
@RunInMain
def StopPLC(self):
@@ -510,7 +520,7 @@
@RunInMain
def SeedBlob(self, seed):
blob = (mkstemp(dir=self.tmpdir) + (hashlib.new('md5'),))
- _fobj, _path, md5sum = blob
+ _fd, _path, md5sum = blob
md5sum.update(seed)
newBlobID = md5sum.digest()
self.blobs[newBlobID] = blob
@@ -523,17 +533,17 @@
if blob is None:
return None
- fobj, _path, md5sum = blob
+ fd, _path, md5sum = blob
md5sum.update(data)
newBlobID = md5sum.digest()
- os.write(fobj, data)
+ os.write(fd, data)
self.blobs[newBlobID] = blob
return newBlobID
@RunInMain
def PurgeBlobs(self):
- for fobj, _path, _md5sum in self.blobs.values():
- os.close(fobj)
+ for fd, _path, _md5sum in self.blobs.values():
+ os.close(fd)
self._init_blobs()
def _BlobAsFile(self, blobID, newpath):
@@ -542,8 +552,11 @@
if blob is None:
raise Exception(_("Missing data to create file: {}").format(newpath))
- fobj, path, _md5sum = blob
- os.close(fobj)
+ fd, path, _md5sum = blob
+ fobj = os.fdopen(fd)
+ fobj.flush()
+ os.fsync(fd)
+ fobj.close()
shutil.move(path, newpath)
def _extra_files_log_path(self):
@@ -599,9 +612,6 @@
# Create new PLC file
self._BlobAsFile(plc_object, new_PLC_filename)
- # Store new PLC filename based on md5 key
- open(self._GetMD5FileName(), "w").write(md5sum)
-
# Then write the files
log = open(extra_files_log, "w")
for fname, blobID in extrafiles:
@@ -609,6 +619,12 @@
self._BlobAsFile(blobID, fpath)
log.write(fname+'\n')
+ # Store new PLC filename based on md5 key
+ with open(self._GetMD5FileName(), "w") as f:
+ f.write(md5sum)
+ f.flush()
+ os.fsync(f.fileno())
+
# Store new PLC filename
self.CurrentPLCFilename = NewFileName
except Exception: