Merge
authorTomaz Orac
Tue, 16 Jun 2020 15:53:52 +0200
changeset 2678 45f1ff6a7f87
parent 2677 556935640ec0 (current diff)
parent 2653 8b612b357679 (diff)
child 2679 2783906d5792
Merge
runtime/PLCObject.py
--- 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: