etherlab/runtime_etherlab.py
author Andrey Skvortsov <andrej.skvortzov@gmail.com>
Fri, 12 Oct 2018 13:24:47 +0300
changeset 2457 9deec258ab1a
parent 2422 45aa510d7a2a
child 2643 b98d9e08231f
permissions -rw-r--r--
python3 support: pylint, W1633 # (round-builtin) round built-in referenced

because round behavior is changed to default behavior in Python3
(Banker round). It can cause slight differences in some cases.
Mostly graphical editors are affected, there could be single pixel differences.
Now I couldn't locate any visual differences in test programs.
2405
af050469fc5c clean etherlab: pylint, W1618 # (no-absolute-import) import missing `from __future__ import absolute_import`
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2404
diff changeset
     1
from __future__ import absolute_import
2357
7c67286cddbe cleanup etherlab: pep8, E401 multiple imports on one line
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2355
diff changeset
     2
import os
2404
87eb184414bd clean etherlab: pylint,E0602 # (undefined-variable) Undefined variable 'X'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2401
diff changeset
     3
import signal
2357
7c67286cddbe cleanup etherlab: pep8, E401 multiple imports on one line
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2355
diff changeset
     4
import subprocess
7c67286cddbe cleanup etherlab: pep8, E401 multiple imports on one line
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2355
diff changeset
     5
import ctypes
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
     6
from threading import Thread
2357
7c67286cddbe cleanup etherlab: pep8, E401 multiple imports on one line
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2355
diff changeset
     7
import time
7c67286cddbe cleanup etherlab: pep8, E401 multiple imports on one line
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2355
diff changeset
     8
import re
2404
87eb184414bd clean etherlab: pylint,E0602 # (undefined-variable) Undefined variable 'X'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2401
diff changeset
     9
87eb184414bd clean etherlab: pylint,E0602 # (undefined-variable) Undefined variable 'X'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2401
diff changeset
    10
import runtime.PLCObject as PLCObject
2401
fe887446134d clean etherlab: pylint, E0611 # (no-name-in-module) No name 'X' in module 'Y'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2396
diff changeset
    11
from runtime.loglevels import LogLevelsDict
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    12
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    13
SDOAnswered = PLCBinary.SDOAnswered
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    14
SDOAnswered.restype = None
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    15
SDOAnswered.argtypes = []
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    16
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    17
SDOThread = None
2132
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
    18
SDOProc = None
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    19
Result = None
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    20
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    21
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    22
def SDOThreadProc(*params):
2132
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
    23
    global Result, SDOProc
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    24
    if params[0] == "upload":
2115
edb49073227e Added error logging when SDO FB fails
Edouard Tisserant
parents: 2114
diff changeset
    25
        cmdfmt = "ethercat upload -p %d -t %s 0x%.4x 0x%.2x"
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    26
    else:
2115
edb49073227e Added error logging when SDO FB fails
Edouard Tisserant
parents: 2114
diff changeset
    27
        cmdfmt = "ethercat download -p %d -t %s 0x%.4x 0x%.2x %s"
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    28
2115
edb49073227e Added error logging when SDO FB fails
Edouard Tisserant
parents: 2114
diff changeset
    29
    command = cmdfmt % params[1:]
2132
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
    30
    SDOProc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
    31
    res = SDOProc.wait()
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
    32
    output = SDOProc.communicate()[0]
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    33
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    34
    if params[0] == "upload":
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    35
        Result = None
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    36
        if res == 0:
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    37
            if params[2] in ["float", "double"]:
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    38
                Result = float(output)
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    39
            elif params[2] in ["string", "octet_string", "unicode_string"]:
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    40
                Result = output
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    41
            else:
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    42
                hex_value, dec_value = output.split()
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    43
                if int(hex_value, 16) == int(dec_value):
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    44
                    Result = int(dec_value)
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    45
    else:
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    46
        Result = res == 0
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    47
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    48
    SDOAnswered()
2375
cfa68a06a24d clean etherlab: pep8, E203 whitespace before ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2372
diff changeset
    49
    if res != 0:
2115
edb49073227e Added error logging when SDO FB fails
Edouard Tisserant
parents: 2114
diff changeset
    50
        PLCObject.LogMessage(
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    51
            LogLevelsDict["WARNING"],
2363
9c7da6ff6a34 cleanup etherlab: pep8, E231 missing whitespace after ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2360
diff changeset
    52
            "%s : %s" % (command, output))
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    53
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    54
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    55
def EthercatSDOUpload(pos, index, subindex, var_type):
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    56
    global SDOThread
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    57
    SDOThread = Thread(target=SDOThreadProc, args=["upload", pos, var_type, index, subindex])
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    58
    SDOThread.start()
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    59
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    60
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    61
def EthercatSDODownload(pos, index, subindex, var_type, value):
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    62
    global SDOThread
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    63
    SDOThread = Thread(target=SDOThreadProc, args=["download", pos, var_type, index, subindex, value])
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    64
    SDOThread.start()
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    65
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    66
2086
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    67
def GetResult():
8e4992e0f147 Adding block library for SDO download and SDO upload
Laurent Bessard
parents:
diff changeset
    68
    return Result
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    69
2370
e40f3914e55f cleanup etherlab: pep8, E305 expected 2 blank lines after class or function definition, found X
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2366
diff changeset
    70
2365
bc07b9910cdb cleanup etherlab: pep8, E225 missing whitespace around operator
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2363
diff changeset
    71
KMSGPollThread = None
bc07b9910cdb cleanup etherlab: pep8, E225 missing whitespace around operator
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2363
diff changeset
    72
StopKMSGThread = False
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    73
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
    74
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    75
def KMSGPollThreadProc():
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    76
    """
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    77
    Logs Kernel messages starting with EtherCAT
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    78
    Uses GLibc wrapper to Linux syscall "klogctl"
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
    79
    Last 4 KB are polled, and lines compared to last
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    80
    captured line to detect new lines
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    81
    """
2365
bc07b9910cdb cleanup etherlab: pep8, E225 missing whitespace around operator
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2363
diff changeset
    82
    libc = ctypes.CDLL("libc.so.6")
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    83
    klog = libc.klogctl
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    84
    klog.argtypes = [ctypes.c_int, ctypes.c_char_p, ctypes.c_int]
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    85
    klog.restype = ctypes.c_int
2365
bc07b9910cdb cleanup etherlab: pep8, E225 missing whitespace around operator
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2363
diff changeset
    86
    s = ctypes.create_string_buffer(4*1024)
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    87
    last = None
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    88
    while not StopKMSGThread:
2372
51f3acc89a58 clean etherlab: pep8, E741 ambiguous variable name 'l'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2370
diff changeset
    89
        bytes_to_read = klog(3, s, len(s)-1)
51f3acc89a58 clean etherlab: pep8, E741 ambiguous variable name 'l'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2370
diff changeset
    90
        log = s.value[:bytes_to_read-1]
2375
cfa68a06a24d clean etherlab: pep8, E203 whitespace before ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2372
diff changeset
    91
        if last:
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    92
            log = log.rpartition(last)[2]
2375
cfa68a06a24d clean etherlab: pep8, E203 whitespace before ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2372
diff changeset
    93
        if log:
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
    94
            last = log.rpartition('\n')[2]
2363
9c7da6ff6a34 cleanup etherlab: pep8, E231 missing whitespace after ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2360
diff changeset
    95
            for lvl, msg in re.findall(
2407
5f2b1bb464a0 clean etherlab: pylint, C0330 # (bad-continuation) Wrong hanging indentation before block
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2405
diff changeset
    96
                    r'<(\d)>\[\s*\d*\.\d*\]\s*(EtherCAT\s*.*)$',
5f2b1bb464a0 clean etherlab: pylint, C0330 # (bad-continuation) Wrong hanging indentation before block
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2405
diff changeset
    97
                    log, re.MULTILINE):
2116
2b1980a038b1 Better logging, saffer failure at init (allows restart)
Edouard Tisserant
parents: 2115
diff changeset
    98
                PLCObject.LogMessage(
2b1980a038b1 Better logging, saffer failure at init (allows restart)
Edouard Tisserant
parents: 2115
diff changeset
    99
                    LogLevelsDict[{
2363
9c7da6ff6a34 cleanup etherlab: pep8, E231 missing whitespace after ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2360
diff changeset
   100
                        "4": "WARNING",
9c7da6ff6a34 cleanup etherlab: pep8, E231 missing whitespace after ','
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2360
diff changeset
   101
                        "3": "CRITICAL"}.get(lvl, "DEBUG")],
2116
2b1980a038b1 Better logging, saffer failure at init (allows restart)
Edouard Tisserant
parents: 2115
diff changeset
   102
                    msg)
2355
fec77f2b9e07 cleanup etherlab: pep8, W291 trailing whitespace
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2353
diff changeset
   103
        time.sleep(0.5)
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   104
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
   105
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   106
def _runtime_etherlab_init():
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   107
    global KMSGPollThread, StopKMSGThread
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   108
    StopKMSGThread = False
2366
d635680e4c2c cleanup etherlab: pep8, E251 unexpected spaces around keyword / parameter equals
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2365
diff changeset
   109
    KMSGPollThread = Thread(target=KMSGPollThreadProc)
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   110
    KMSGPollThread.start()
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   111
2360
2a3d022a7dac cleanup etherlab: pep8, E302 expected 2 blank lines, found 1
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2358
diff changeset
   112
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   113
def _runtime_etherlab_cleanup():
2422
45aa510d7a2a cleanup etherlab: pylint, W0602 (global-variable-not-assigned) Using global for 'X' but no assignment is done
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2407
diff changeset
   114
    global KMSGPollThread, StopKMSGThread, SDOThread
2132
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
   115
    try:
2404
87eb184414bd clean etherlab: pylint,E0602 # (undefined-variable) Undefined variable 'X'
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2401
diff changeset
   116
        os.kill(SDOProc.pid, signal.SIGTERM)
2353
8f1a2846b2f5 cleanup etherlab: pep8, E722 do not use bare except
Andrey Skvortsov <andrej.skvortzov@gmail.com>
parents: 2132
diff changeset
   117
    except Exception:
2132
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
   118
        pass
9f5e4dc43053 Added support for stopping SDOThreadProc when stopping PLC
Laurent Bessard
parents: 2116
diff changeset
   119
    SDOThread = None
2114
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   120
    StopKMSGThread = True
fc1bc441cf71 Added logging based on collecting Kernel logs
Edouard Tisserant
parents: 2086
diff changeset
   121
    KMSGPollThread = None