Adding block library for SDO download and SDO upload
authorLaurent Bessard
Thu, 25 Oct 2012 19:55:02 +0200
changeset 2086 8e4992e0f147
parent 2085 ae263886ae92
child 2087 8421bd1f8b06
Adding block library for SDO download and SDO upload
etherlab/etherlab.py
etherlab/etherlab_ext.c
etherlab/extension.py
etherlab/pous.xml
etherlab/runtime_etherlab.py
--- a/etherlab/etherlab.py	Fri Oct 19 16:37:54 2012 +0200
+++ b/etherlab/etherlab.py	Thu Oct 25 19:55:02 2012 +0200
@@ -5,6 +5,7 @@
 import wx
 
 from xmlclass import *
+from POULibrary import POULibrary
 from ConfigTreeNode import ConfigTreeNode
 from PLCControler import UndoBuffer, LOCATION_CONFNODE, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY
 from ConfigEditor import NodeEditor, CIA402NodeEditor, ETHERCAT_VENDOR, ETHERCAT_GROUP, ETHERCAT_DEVICE
@@ -56,6 +57,31 @@
 """
 
 #--------------------------------------------------
+#      Etherlab Specific Blocks Library
+#--------------------------------------------------
+
+def GetLocalPath(filename):
+    return os.path.join(os.path.split(__file__)[0], filename)
+
+class EtherlabLibrary(POULibrary):
+    def GetLibraryPath(self):
+        return GetLocalPath("pous.xml")
+
+    def Generate_C(self, buildpath, varlist, IECCFLAGS):
+        etherlab_ext_file = open(GetLocalPath("etherlab_ext.c"), 'r')
+        etherlab_ext_code = etherlab_ext_file.read()
+        etherlab_ext_file.close()
+        
+        Gen_etherlabfile_path = os.path.join(buildpath, "etherlab_ext.c")
+        ethelabfile = open(Gen_etherlabfile_path,'w')
+        ethelabfile.write(etherlab_ext_code)
+        ethelabfile.close()
+        
+        runtimefile_path = os.path.join(os.path.split(__file__)[0], "runtime_etherlab.py")
+        return ((["etherlab_ext"], [(Gen_etherlabfile_path, IECCFLAGS)], True), "", 
+                ("runtime_etherlab.py", file(GetLocalPath("runtime_etherlab.py"))))
+
+#--------------------------------------------------
 #                    Ethercat Node
 #--------------------------------------------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/etherlab_ext.c	Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,42 @@
+#include "iec_types_all.h"
+
+#define FREE 0
+#define ACQUIRED 1
+#define ANSWERED 2
+
+long SDOLock = FREE;
+extern long AtomicCompareExchange(long* atomicvar,long compared, long exchange);
+
+int AcquireSDOLock() {
+	return AtomicCompareExchange(&SDOLock, FREE, ACQUIRED) == FREE;
+}
+
+void SDOAnswered() {
+	AtomicCompareExchange(&SDOLock, ACQUIRED, ANSWERED);
+}
+
+int HasAnswer() {
+	return SDOLock == ANSWERED;
+}
+
+void ReleaseSDOLock() {
+	AtomicCompareExchange(&SDOLock, ANSWERED, FREE);
+}
+
+int __init_etherlab_ext()
+{
+    SDOLock = FREE;
+    return 0;
+}
+
+void __cleanup_etherlab_ext()
+{
+}
+
+void __retrieve_etherlab_ext()
+{
+}
+
+void __publish_etherlab_ext()
+{
+}
--- a/etherlab/extension.py	Fri Oct 19 16:37:54 2012 +0200
+++ b/etherlab/extension.py	Thu Oct 25 19:55:02 2012 +0200
@@ -1,5 +1,12 @@
 import features
 
+def GetEtherLabLibClass():
+    from etherlab import EtherlabLibrary
+    return EtherlabLibrary
+
+features.libraries.append(
+    ('Etherlab', GetEtherLabLibClass))
+
 def GetEtherLabClass():
     from etherlab import RootClass
     return RootClass
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/pous.xml	Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://www.plcopen.org/xml/tc6.xsd"
+         xsi:schemaLocation="http://www.plcopen.org/xml/tc6.xsd"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns:xhtml="http://www.w3.org/1999/xhtml">
+  <fileHeader companyName="EtherlabMaster"
+              productName="EtherlabMaster"
+              productVersion="1"
+              creationDateTime="2012-10-22T12:12:45"/>
+  <contentHeader name="EtherlabMaster SDO Blocks"
+                 modificationDateTime="2012-10-25T19:53:33">
+    <coordinateInfo>
+      <fbd>
+        <scaling x="0" y="0"/>
+      </fbd>
+      <ld>
+        <scaling x="0" y="0"/>
+      </ld>
+      <sfc>
+        <scaling x="0" y="0"/>
+      </sfc>
+    </coordinateInfo>
+  </contentHeader>
+  <types>
+    <dataTypes/>
+    <pous>
+      <pou name="EtherLabSDOUpload" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="EXECUTE">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="POS">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+            <variable name="INDEX">
+              <type>
+                <UINT/>
+              </type>
+            </variable>
+            <variable name="SUBINDEX">
+              <type>
+                <USINT/>
+              </type>
+            </variable>
+            <variable name="VARTYPE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="ACK">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="VALID">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="VALUE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="PY0">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="PY1">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="EXECUTE0">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="STATE">
+              <type>
+                <INT/>
+              </type>
+              <initialValue>
+                <simpleValue value="0"/>
+              </initialValue>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[{extern int AcquireSDOLock();}
+{extern int HasAnswer();}
+{extern void ReleaseSDOLock();}
+CASE STATE OF
+  0:
+    IF EXECUTE AND NOT EXECUTE0 THEN
+      STATE := 1;
+      ACK := 0;
+      VALID := 0;
+      VALUE := 'None';
+    END_IF;
+  1:
+    {if (AcquireSDOLock()) __SET_VAR(data__->,STATE, 2)}
+  2:
+    IF PY0.ACK THEN
+      STATE := 3;
+    END_IF;
+  3:
+    {if (HasAnswer()) __SET_VAR(data__->,STATE, 4)}
+  4:
+    IF PY1.ACK THEN
+      ACK := 1;
+      VALUE := PY1.RESULT;
+      VALID := NE(VALUE, 'None');
+      STATE := 0;
+      {ReleaseSDOLock();}
+    END_IF;
+ELSE
+  STATE := 0;
+END_CASE;
+
+EXECUTE0 := EXECUTE;
+PY0(TRIG := STATE = 2, 
+    CODE := CONCAT('EthercatSDOUpload(',
+                   INT_TO_STRING(POS),
+                   ',',
+                   UINT_TO_STRING(INDEX),
+                   ',',
+                   USINT_TO_STRING(SUBINDEX),
+                   ',"',
+                   VARTYPE,
+                   '")'));
+PY1(TRIG := STATE = 4, 
+    CODE := 'GetResult()');
+]]>
+          </ST>
+        </body>
+      </pou>
+      <pou name="EtherLabSDODownload" pouType="functionBlock">
+        <interface>
+          <inputVars>
+            <variable name="EXECUTE">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="POS">
+              <type>
+                <INT/>
+              </type>
+            </variable>
+            <variable name="INDEX">
+              <type>
+                <UINT/>
+              </type>
+            </variable>
+            <variable name="SUBINDEX">
+              <type>
+                <USINT/>
+              </type>
+            </variable>
+            <variable name="VARTYPE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+            <variable name="VALUE">
+              <type>
+                <string/>
+              </type>
+            </variable>
+          </inputVars>
+          <outputVars>
+            <variable name="ACK">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="ERROR">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+          </outputVars>
+          <localVars>
+            <variable name="PY0">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="PY1">
+              <type>
+                <derived name="python_eval"/>
+              </type>
+            </variable>
+            <variable name="EXECUTE0">
+              <type>
+                <BOOL/>
+              </type>
+            </variable>
+            <variable name="STATE">
+              <type>
+                <INT/>
+              </type>
+              <initialValue>
+                <simpleValue value="0"/>
+              </initialValue>
+            </variable>
+          </localVars>
+        </interface>
+        <body>
+          <ST>
+<![CDATA[{extern int AcquireSDOLock();}
+{extern int HasAnswer();}
+{extern void ReleaseSDOLock();}
+CASE STATE OF
+  0:
+    IF EXECUTE AND NOT EXECUTE0 THEN
+      STATE := 1;
+      ACK := 0;
+      ERROR := 0;
+    END_IF;
+  1:
+    {if (AcquireSDOLock()) __SET_VAR(data__->,STATE, 2)}
+  2:
+    IF PY0.ACK THEN
+      STATE := 3;
+    END_IF;
+  3:
+    {if (HasAnswer()) __SET_VAR(data__->,STATE, 4)}
+  4:
+    IF PY1.ACK THEN
+      ACK := 1;
+      VALUE := PY1.RESULT;
+      ERROR := EQ(PY1.RESULT, 'False');
+      STATE := 0;
+      {ReleaseSDOLock();}
+    END_IF;
+ELSE
+  STATE := 0;
+END_CASE;
+EXECUTE0 := EXECUTE;
+PY0(TRIG := STATE = 2, 
+    CODE := CONCAT('EthercatSDODownload(',
+                   INT_TO_STRING(POS),
+                   ',',
+                   UINT_TO_STRING(INDEX),
+                   ',',
+                   USINT_TO_STRING(SUBINDEX),
+                   ',"',
+                   VARTYPE,
+                   '",',
+                   VALUE,
+                   ')'));
+PY1(TRIG := STATE = 4, 
+    CODE := 'GetResult()');
+]]>
+          </ST>
+        </body>
+      </pou>
+    </pous>
+  </types>
+  <instances>
+    <configurations/>
+  </instances>
+</project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/etherlab/runtime_etherlab.py	Thu Oct 25 19:55:02 2012 +0200
@@ -0,0 +1,50 @@
+import subprocess,sys,ctypes
+from threading import Thread
+
+SDOAnswered = PLCBinary.SDOAnswered
+SDOAnswered.restype = None
+SDOAnswered.argtypes = []
+
+SDOThread = None
+Result = None
+
+def SDOThreadProc(*params):
+    global Result
+    if params[0] == "upload":
+        command = "ethercat upload -p %d -t %s 0x%.4x 0x%.2x"
+    else:
+        command = "ethercat download -p %d -t %s 0x%.4x 0x%.2x %s"
+    
+    proc = subprocess.Popen(command % params[1:], stdout=subprocess.PIPE, shell=True)
+    res = proc.wait()
+    output = proc.communicate()[0]
+    
+    if params[0] == "upload":
+        Result = None
+        if res == 0:
+            if params[2] in ["float", "double"]:
+                Result = float(output)
+            elif params[2] in ["string", "octet_string", "unicode_string"]:
+                Result = output
+            else:
+                hex_value, dec_value = output.split()
+                if int(hex_value, 16) == int(dec_value):
+                    Result = int(dec_value)
+    else:
+        Result = res == 0
+    
+    SDOAnswered()
+    
+def EthercatSDOUpload(pos, index, subindex, var_type):
+    global SDOThread
+    SDOThread = Thread(target=SDOThreadProc, args=["upload", pos, var_type, index, subindex])
+    SDOThread.start()
+    
+def EthercatSDODownload(pos, index, subindex, var_type, value):
+    global SDOThread
+    SDOThread = Thread(target=SDOThreadProc, args=["download", pos, var_type, index, subindex, value])
+    SDOThread.start()
+
+def GetResult():
+    global Result
+    return Result