Uses pycomm_helper package instead of that janky old tag package
This commit is contained in:
14
daq/Dockerfile.rpi
Normal file
14
daq/Dockerfile.rpi
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM patrickjmcd/rpi-python3:latest
|
||||
|
||||
# Copy source files
|
||||
RUN mkdir /root/tag-logger
|
||||
COPY taglogger.py /root/tag-logger/taglogger.py
|
||||
COPY pycomm-master /tmp/pycomm
|
||||
COPY pycomm_helper /tmp/pycomm_helper
|
||||
|
||||
# Install some python packages
|
||||
RUN pip install requests
|
||||
RUN cd /tmp/pycomm && python setup.py install && cd /
|
||||
RUN cd /tmp/pycomm_helper && python setup.py install && cd /
|
||||
|
||||
CMD ["python", "/root/tag-logger/taglogger.py"]
|
||||
14
daq/Dockerfile.ubuntu
Normal file
14
daq/Dockerfile.ubuntu
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM python:latest
|
||||
|
||||
# Copy source files
|
||||
RUN mkdir /root/tag-logger
|
||||
COPY taglogger.py /root/tag-logger/taglogger.py
|
||||
COPY pycomm-master /tmp/pycomm
|
||||
COPY pycomm_helper /tmp/pycomm_helper
|
||||
|
||||
# Install some python packages
|
||||
RUN pip install requests
|
||||
RUN cd /tmp/pycomm && python setup.py install && cd /
|
||||
RUN cd /tmp/pycomm_helper && python setup.py install && cd /
|
||||
|
||||
CMD ["python", "/root/tag-logger/taglogger.py"]
|
||||
1
daq/pycomm_helper
Submodule
1
daq/pycomm_helper
Submodule
Submodule daq/pycomm_helper added at a3b6c088c5
3
daq/tag/.gitmodules
vendored
3
daq/tag/.gitmodules
vendored
@@ -1,3 +0,0 @@
|
||||
[submodule "micro800"]
|
||||
path = micro800
|
||||
url = http://patrickjmcd@bitbucket.poconsole.net/scm/poconsole/micro800.git
|
||||
126
daq/tag/alarm.py
126
daq/tag/alarm.py
@@ -1,126 +0,0 @@
|
||||
#! /usr/bin/python
|
||||
# from datetime import datetime
|
||||
import time
|
||||
from pycomm.ab_comm.clx import Driver as ClxDriver
|
||||
import tag.micro800.micro800 as u800
|
||||
import requests
|
||||
import json
|
||||
# import traceback
|
||||
# import pickle
|
||||
|
||||
web_address = "http://localhost:3000"
|
||||
|
||||
|
||||
def readTag(addr, tag):
|
||||
time.sleep(0.01)
|
||||
c = ClxDriver()
|
||||
if c.open(addr):
|
||||
try:
|
||||
v = c.read_tag(tag)
|
||||
return v
|
||||
except Exception:
|
||||
print("ERROR RETRIEVING TAG: {} at {}".format(tag, addr))
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print err
|
||||
pass
|
||||
c.close()
|
||||
|
||||
|
||||
class AnalogAlarm():
|
||||
global readTag, con
|
||||
|
||||
def __init__(self, name, tag, db_id, device_type='CLX', ip_address='192.168.1.10'):
|
||||
self.name = name
|
||||
self.tag = tag
|
||||
self.alarm = False
|
||||
self.warning = False
|
||||
self.lastAlarmCheckVal = False
|
||||
self.lastWarningCheckVal = False
|
||||
self.device_type = device_type
|
||||
self.readFn = readTag
|
||||
self.db_id = db_id
|
||||
if self.device_type == "u800":
|
||||
self.readFn = u800.readTag
|
||||
self.ip_address = ip_address
|
||||
self.condMapFn = {
|
||||
20: "Low",
|
||||
21: "High",
|
||||
24: "LoLo",
|
||||
25: "HiHi",
|
||||
32: "Input Failure",
|
||||
34: "Configuration Error",
|
||||
16: "Failure to Stop",
|
||||
17: "Failure to Start",
|
||||
18: "Drive Fault"
|
||||
}
|
||||
|
||||
def checkStatus(self, stroke_number):
|
||||
condition = ''
|
||||
|
||||
self.alarm = self.readFn(self.ip_address, '{}.Alarm'.format(self.tag))[0] > 0
|
||||
alarmChanged = not (self.alarm == self.lastAlarmCheckVal)
|
||||
|
||||
self.warning = self.readFn(self.ip_address, '{}.Warning'.format(self.tag))[0] > 0
|
||||
warningChanged = not (self.warning == self.lastWarningCheckVal)
|
||||
|
||||
if (alarmChanged and self.alarm) or (warningChanged and self.warning):
|
||||
condition = self.condMapFn[int(self.readFn(self.ip_address, '{}.Alarm_Code'.format(self.tag))[0])]
|
||||
value = self.readFn(self.ip_address, '{}.Alarm_Value'.format(self.tag))[0]
|
||||
triggerType = "Alarm"
|
||||
if warningChanged:
|
||||
triggerType = 'Warning'
|
||||
|
||||
data = {
|
||||
'alarmID': self.db_id,
|
||||
'type': triggerType,
|
||||
'cond': condition,
|
||||
'value': value,
|
||||
'stroke_number': stroke_number
|
||||
}
|
||||
|
||||
r = requests.post('{}/event'.format(web_address), data=data)
|
||||
resp = json.loads(r.text)
|
||||
print("Stored Event {} at {}".format(resp['id'], resp['createdAt']))
|
||||
|
||||
if warningChanged:
|
||||
self.lastWarningCheckVal = self.warning
|
||||
|
||||
if alarmChanged:
|
||||
self.lastAlarmCheckVal = self.alarm
|
||||
|
||||
|
||||
class bitAlarm():
|
||||
def __init__(self, name, tag, condition, db_id, device_type='CLX', ip_address='192.168.1.10'):
|
||||
self.name = name
|
||||
self.tag = tag
|
||||
self.condition = condition
|
||||
self.status = False
|
||||
self.lastStatusCheckVal = False
|
||||
self.device_type = device_type
|
||||
self.readFn = readTag
|
||||
self.db_id = db_id
|
||||
if self.device_type == "u800":
|
||||
self.readFn = u800.readTag
|
||||
self.ip_address = ip_address
|
||||
|
||||
def checkStatus(self, stroke_number):
|
||||
|
||||
self.status = self.readFn(self.ip_address, self.tag)[0] > 0
|
||||
statusChanged = not (self.status == self.lastStatusCheckVal)
|
||||
|
||||
if statusChanged and self.status:
|
||||
data = {
|
||||
'alarmID': self.db_id,
|
||||
'type': "Info",
|
||||
'cond': self.condition,
|
||||
'value': 0.0,
|
||||
'stroke_number': stroke_number
|
||||
}
|
||||
|
||||
r = requests.post('{}/event'.format(web_address), data=data)
|
||||
resp = json.loads(r.text)
|
||||
print("Stored Event {} at {}".format(resp['id'], resp['createdAt']))
|
||||
|
||||
if statusChanged:
|
||||
self.lastStatusCheckVal = self.status
|
||||
@@ -1,119 +0,0 @@
|
||||
from pycomm.ab_comm.clx import Driver as plcDriver
|
||||
import sys
|
||||
|
||||
|
||||
def readMicroTag(addr, tag):
|
||||
addr = str(addr)
|
||||
tag = str(tag)
|
||||
c = plcDriver()
|
||||
if c.open(addr, True):
|
||||
try:
|
||||
v = c.read_tag(tag)
|
||||
# print(v)
|
||||
return v
|
||||
except Exception:
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print("{} on reading {} from {}".format(err, tag, addr))
|
||||
pass
|
||||
c.close()
|
||||
|
||||
|
||||
def getTagType(addr, tag):
|
||||
addr = str(addr)
|
||||
tag = str(tag)
|
||||
c = plcDriver()
|
||||
if c.open(addr, True):
|
||||
try:
|
||||
return c.read_tag(tag)[1]
|
||||
except Exception:
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print(err)
|
||||
pass
|
||||
c.close()
|
||||
|
||||
|
||||
def write(addr, tag, val, t):
|
||||
addr = str(addr)
|
||||
tag = str(tag)
|
||||
c = plcDriver()
|
||||
if c.open(addr, True):
|
||||
try:
|
||||
wt = c.write_tag(tag, val, t)
|
||||
return wt
|
||||
except Exception:
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print("Write Error: {} setting {} at {} to {} type {}".format(err, tag, addr, val, t))
|
||||
return False
|
||||
c.close()
|
||||
|
||||
|
||||
def closeEnough(a, b):
|
||||
return abs(a - b) <= 0.001
|
||||
|
||||
|
||||
def writeMicroTag(addr, tag, val, handshake=None, handshake_val=None):
|
||||
addr = str(addr)
|
||||
tag = str(tag)
|
||||
print("handshake: {}, handshake_val: {}".format(handshake, handshake_val))
|
||||
chk_tag = tag
|
||||
if not(handshake is None) and not(handshake == "None"):
|
||||
chk_tag = str(handshake)
|
||||
print("Handshake tag passed, using {}".format(chk_tag))
|
||||
chk_val = val
|
||||
if not (handshake_val is None) and not(handshake_val == "None"):
|
||||
chk_val = handshake_val
|
||||
print("Handshake value passed, using {}".format(chk_val))
|
||||
attempts_allowed = 5
|
||||
attempts = 1
|
||||
|
||||
while attempts <= attempts_allowed:
|
||||
try:
|
||||
attempts = attempts + 1
|
||||
cv = readMicroTag(addr, tag)
|
||||
print("Val Before Write: {}".format(cv))
|
||||
if cv:
|
||||
if cv[1] == "REAL":
|
||||
val = float(val)
|
||||
chk_val = float(chk_val)
|
||||
else:
|
||||
val = int(val)
|
||||
chk_val = int(chk_val)
|
||||
wt = write(addr, tag, val, cv[1])
|
||||
if wt:
|
||||
print("write: {}".format(wt))
|
||||
chk = readMicroTag(addr, chk_tag)
|
||||
if chk:
|
||||
print("chk: {}, chk_val: {}".format(chk, chk_val))
|
||||
if closeEnough(chk[0], chk_val):
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
|
||||
def readMicroTagList(addr, tList):
|
||||
addr = str(addr)
|
||||
c = plcDriver()
|
||||
if c.open(addr, True):
|
||||
vals = []
|
||||
try:
|
||||
for t in tList:
|
||||
v = c.read_tag(t)
|
||||
vals.append({"tag": t, "val": v[0], "type": v[1]})
|
||||
# print(v)
|
||||
# print("{0} - {1}".format(t, v))
|
||||
except Exception:
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print(err)
|
||||
pass
|
||||
c.close()
|
||||
return vals
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 2:
|
||||
print(readMicroTag(sys.argv[1], sys.argv[2]))
|
||||
else:
|
||||
print ("Did not pass a target and tag name.")
|
||||
@@ -1,32 +0,0 @@
|
||||
__author__ = 'Agostino Ruscito'
|
||||
__version__ = "1.0.7"
|
||||
__date__ = "08 03 2015"
|
||||
import logging
|
||||
|
||||
|
||||
logging.basicConfig(
|
||||
filename="pycomm.log",
|
||||
filemode='w',
|
||||
level=logging.INFO,
|
||||
format="%(name)-13s %(levelname)-10s %(asctime)s %(message)s",
|
||||
# propagate=0,
|
||||
)
|
||||
|
||||
LOGGER = logging.getLogger('pycomm')
|
||||
|
||||
|
||||
class PycommError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def setup_logger(name, level, filename=None):
|
||||
log = logging.getLogger('pycomm.'+name)
|
||||
log.setLevel(level)
|
||||
if filename:
|
||||
fh = logging.FileHandler(filename, mode='w')
|
||||
fh.setFormatter(logging.Formatter("%(levelname)-10s %(asctime)s %(message)s"))
|
||||
log.addHandler(fh)
|
||||
log.propagate = False
|
||||
|
||||
return log
|
||||
|
||||
107
daq/tag/tag.py
107
daq/tag/tag.py
@@ -1,107 +0,0 @@
|
||||
#! /usr/bin/python
|
||||
# from datetime import datetime
|
||||
import time
|
||||
from pycomm.ab_comm.clx import Driver as ClxDriver
|
||||
import tag.micro800.micro800 as u800
|
||||
import requests
|
||||
import json
|
||||
# import traceback
|
||||
# import pickle
|
||||
|
||||
web_address = "https://10.10.10.10:3000"
|
||||
|
||||
|
||||
def readTag(addr, tag):
|
||||
time.sleep(0.01)
|
||||
c = ClxDriver()
|
||||
if c.open(addr):
|
||||
try:
|
||||
v = c.read_tag(tag)
|
||||
return v
|
||||
except Exception:
|
||||
print("ERROR RETRIEVING TAG: {} at {}".format(tag, addr))
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print(err)
|
||||
pass
|
||||
c.close()
|
||||
|
||||
def writeTag(addr, tag, val):
|
||||
time.sleep(0.01)
|
||||
pv = readTag(addr, tag)
|
||||
if pv:
|
||||
c = ClxDriver()
|
||||
if c.open(addr):
|
||||
try:
|
||||
v = c.write_tag(tag, val, pv[1])
|
||||
return v
|
||||
except Exception:
|
||||
print("ERROR WRITING TAG: {} at {}".format(tag, addr))
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print(err)
|
||||
pass
|
||||
c.close()
|
||||
|
||||
class Tag():
|
||||
global readTag, writeTag, web_address
|
||||
|
||||
def __init__(self, name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'):
|
||||
self.name = name
|
||||
self.tag = tag
|
||||
self.data_type = data_type
|
||||
self.value = None
|
||||
self.last_value = None
|
||||
self.guarantee_sec = guarantee_sec
|
||||
self.chg_threshold = change_threshold
|
||||
self.last_send_time = 0
|
||||
self.mapFn = mapFn
|
||||
self.device_type = device_type
|
||||
self.readFn = readTag
|
||||
self.writeFn = writeTag
|
||||
self.db_id = db_id
|
||||
if self.device_type == "u800" or self.device_type == "Micro800":
|
||||
self.readFn = u800.readMicroTag
|
||||
self.writeFn = u800.writeMicroTag
|
||||
self.ip_address = ip_address
|
||||
|
||||
def read(self, forceSend):
|
||||
writeToDB = False
|
||||
if self.tag:
|
||||
v = self.readFn(str(self.ip_address), str(self.tag))
|
||||
if v:
|
||||
val = v[0]
|
||||
if self.data_type == 'BOOL' or self.data_type == 'STRING':
|
||||
if self.mapFn:
|
||||
val = self.mapFn[val]
|
||||
if (self.last_send_time == 0) or (self.value is None) or not (self.value == val) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend is True):
|
||||
self.last_value = self.value
|
||||
self.value = val
|
||||
writeToDB = True
|
||||
else:
|
||||
writeToDB = False
|
||||
else:
|
||||
if (self.last_send_time == 0) or (self.value is None) or (abs(self.value - v[0]) > self.chg_threshold) or ((time.time() - self.last_send_time) > self.guarantee_sec) or (forceSend is True):
|
||||
self.last_value = self.value
|
||||
self.value = v[0]
|
||||
writeToDB = True
|
||||
else:
|
||||
writeToDB = False
|
||||
if forceSend is False:
|
||||
writeToDB = False
|
||||
if writeToDB:
|
||||
self.sendToDB()
|
||||
return self.value
|
||||
|
||||
def write(self, value):
|
||||
if self.tag:
|
||||
w = self.writeFn(str(self.ip_address), str(self.tag), value)
|
||||
|
||||
def sendToDB(self):
|
||||
data = {}
|
||||
data['val'] = self.value
|
||||
data['tagID'] = self.db_id
|
||||
r = requests.post('{}/tag_val'.format(web_address), data=data, verify=False)
|
||||
resp = json.loads(r.text)
|
||||
print("Stored {} for {} at {}".format(resp['val'], self.name, resp['createdAt']))
|
||||
self.last_send_time = time.time()
|
||||
@@ -11,10 +11,11 @@ import traceback
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
from tag.tag import Tag
|
||||
from pycomm_helper.tag import Tag
|
||||
|
||||
# DEFAULTS
|
||||
web_address = "https://10.10.10.10:3000"
|
||||
db_address = "10.10.10.10:3000"
|
||||
db_url = "https://{}".format(db_address)
|
||||
scan_rate = 30 # seconds
|
||||
save_all = "test" # use True, False, or any string
|
||||
plc_handshake_tags = {}
|
||||
@@ -25,11 +26,11 @@ device_types = {}
|
||||
|
||||
|
||||
def main():
|
||||
global web_address, scan_rate, save_all, tag_store, device_types, plc_handshake_tags, last_handshake_time
|
||||
global db_address, scan_rate, save_all, tag_store, device_types, plc_handshake_tags, last_handshake_time
|
||||
try:
|
||||
# Get tags stored in database
|
||||
get_tag_request_data = {'where': '{"tag_class": 5}'}
|
||||
get_tag_request = requests.get('{}/tag'.format(web_address), params=get_tag_request_data, verify=False)
|
||||
get_tag_request = requests.get('{}/tag'.format(db_url), params=get_tag_request_data, verify=False)
|
||||
tags = json.loads(get_tag_request.text)
|
||||
except Exception as e:
|
||||
print("Error getting tags: {}".format(e))
|
||||
@@ -39,7 +40,7 @@ def main():
|
||||
try:
|
||||
# Get tags stored in database
|
||||
|
||||
get_device_type_request = requests.get('{}/device_type'.format(web_address), verify=False)
|
||||
get_device_type_request = requests.get('{}/device_type'.format(db_url), verify=False)
|
||||
device_types_json = json.loads(get_device_type_request.text)
|
||||
for t in device_types_json:
|
||||
device_types[t['id']] = t['dType']
|
||||
@@ -50,7 +51,7 @@ def main():
|
||||
|
||||
try:
|
||||
sr_req_data = 'where={"parameter": "scan_rate"}'
|
||||
sr_req = requests.get('{}/config?{}'.format(web_address, sr_req_data), verify=False)
|
||||
sr_req = requests.get('{}/config?{}'.format(db_url, sr_req_data), verify=False)
|
||||
sr_try = json.loads(sr_req.text)
|
||||
if len(sr_try) > 0:
|
||||
scan_rate = int(sr_try[0]['val'])
|
||||
@@ -60,7 +61,7 @@ def main():
|
||||
|
||||
try:
|
||||
sa_req_data = {"where": {"parameter": "save_all"}}
|
||||
sa_req = requests.get('{}/config'.format(web_address), params=sa_req_data, verify=False)
|
||||
sa_req = requests.get('{}/config'.format(db_url), params=sa_req_data, verify=False)
|
||||
sa_try = json.loads(sa_req.text)
|
||||
if len(sa_try) > 0:
|
||||
if sa_try[0]['val'].lower() == "true":
|
||||
@@ -74,7 +75,7 @@ def main():
|
||||
try:
|
||||
# Get tags stored in database
|
||||
get_hs_request_data = {'where': '{"tag_class": 6}'}
|
||||
get_hs_request = requests.get('{}/tag'.format(web_address), params=get_hs_request_data, verify=False)
|
||||
get_hs_request = requests.get('{}/tag'.format(db_url), params=get_hs_request_data, verify=False)
|
||||
hs_tags = json.loads(get_hs_request.text)
|
||||
if len(hs_tags) > 0:
|
||||
for hs in hs_tags:
|
||||
@@ -84,7 +85,7 @@ def main():
|
||||
|
||||
for t in tags:
|
||||
# name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'):
|
||||
tag_store[t['name']] = Tag(t['name'], t['tag'], t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'], device_type=device_types[t['deviceID']['device_type']])
|
||||
tag_store[t['name']] = Tag(t['name'], t['tag'], t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'], device_type=device_types[t['deviceID']['device_type']], db_address=db_address)
|
||||
|
||||
while True:
|
||||
for tag in tag_store:
|
||||
|
||||
14
daq_sample/Dockerfile.rpi
Normal file
14
daq_sample/Dockerfile.rpi
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM patrickjmcd/rpi-python3:latest
|
||||
|
||||
# Copy source files
|
||||
RUN mkdir /root/tag-logger
|
||||
COPY sampleData.py /root/tag-logger/sampleData.py
|
||||
COPY pycomm-master /tmp/pycomm
|
||||
COPY pycomm_helper /tmp/pycomm_helper
|
||||
|
||||
# Install some python packages
|
||||
RUN pip install requests
|
||||
RUN cd /tmp/pycomm && python setup.py install && cd /
|
||||
RUN cd /tmp/pycomm_helper && python setup.py install && cd /
|
||||
|
||||
CMD ["python", "/root/tag-logger/sampleData.py"]
|
||||
@@ -1,15 +1,14 @@
|
||||
FROM python:latest
|
||||
|
||||
# Copy source files
|
||||
RUN mkdir /root/tag-logger
|
||||
COPY taglogger.py /root/tag-logger/taglogger.py
|
||||
COPY sampleData.py /root/tag-logger/sampleData.py
|
||||
COPY tag /root/tag-logger/tag
|
||||
COPY pycomm-master /tmp/pycomm
|
||||
COPY pycomm_helper /tmp/pycomm_helper
|
||||
|
||||
# RUN wget https://bootstrap.pypa.io/get-pip.py
|
||||
# RUN python get-pip.py
|
||||
|
||||
# Install some python packages
|
||||
RUN pip install requests
|
||||
RUN cd /tmp/pycomm && python setup.py install && cd /
|
||||
RUN cd /tmp/pycomm_helper && python setup.py install && cd /
|
||||
|
||||
CMD ["python", "/root/tag-logger/sampleData.py"]
|
||||
12
daq_sample/pycomm-master/.travis.yml
Executable file
12
daq_sample/pycomm-master/.travis.yml
Executable file
@@ -0,0 +1,12 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- "2.6"
|
||||
- "2.7"
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
|
||||
install: python setup.py install
|
||||
|
||||
script: nosetests
|
||||
39
daq_sample/pycomm-master/CHANGES
Executable file
39
daq_sample/pycomm-master/CHANGES
Executable file
@@ -0,0 +1,39 @@
|
||||
CHANGES
|
||||
=======
|
||||
|
||||
1.0.8
|
||||
-----
|
||||
Number 0001:
|
||||
handling of raw values (hex) added to functions read_array and write_array: handling of raw values can be switched
|
||||
on/off with additional parameter
|
||||
|
||||
Number 0002:
|
||||
is a bugfix when reading the tag_list from a PLC. If one tag is of datatype bool and it is part of a bool
|
||||
array within an SINT, the tag type value contains also the bit position.
|
||||
|
||||
Number 0003:
|
||||
code is always logging into a file (pycomm.log) into working path. Code changed, so that it is possible to configure
|
||||
the logging from the main application.
|
||||
|
||||
|
||||
|
||||
1.0.6
|
||||
-----
|
||||
|
||||
- Pypi posting
|
||||
|
||||
1.0.0
|
||||
-----
|
||||
|
||||
- Add support for SLC and PLC/05 plc
|
||||
|
||||
0.2.0
|
||||
---
|
||||
|
||||
- Add CIP support class
|
||||
- Add support for ControlLogix PLC
|
||||
|
||||
0.1
|
||||
---
|
||||
|
||||
- Initial release.
|
||||
22
daq_sample/pycomm-master/LICENSE
Executable file
22
daq_sample/pycomm-master/LICENSE
Executable file
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Agostino Ruscito
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
1
daq_sample/pycomm-master/MANIFEST.in
Executable file
1
daq_sample/pycomm-master/MANIFEST.in
Executable file
@@ -0,0 +1 @@
|
||||
include README.rst
|
||||
171
daq_sample/pycomm-master/README.rst
Executable file
171
daq_sample/pycomm-master/README.rst
Executable file
@@ -0,0 +1,171 @@
|
||||
pycomm
|
||||
======
|
||||
pycomm is a package that includes a collection of modules used to communicate with PLCs.
|
||||
At the moment the first module in the package is ab_comm.
|
||||
|
||||
Test
|
||||
~~~~
|
||||
The library is currently test on Python 2.6, 2.7.
|
||||
|
||||
.. image:: https://travis-ci.org/ruscito/pycomm.svg?branch=master
|
||||
:target: https://travis-ci.org/ruscito/pycomm
|
||||
|
||||
Setup
|
||||
~~~~~
|
||||
The package can be installed from
|
||||
|
||||
GitHub:
|
||||
::
|
||||
|
||||
git clone https://github.com/ruscito/pycomm.git
|
||||
cd pycomm
|
||||
sudo python setup.py install
|
||||
|
||||
|
||||
PyPi:
|
||||
::
|
||||
pip install pycomm
|
||||
|
||||
ab_comm
|
||||
~~~~~~~
|
||||
ab_comm is a module that contains a set of classes used to interface Rockwell PLCs using Ethernet/IP protocol.
|
||||
The "clx" class can be used to communicate with Compactlogix, Controllogix PLCs
|
||||
The "slc" can be used to communicate with Micrologix or SLC PLCs
|
||||
|
||||
I tried to followCIP specifications volume 1 and 2 as well as `Rockwell Automation Publication 1756-PM020-EN-P - November 2012`_ .
|
||||
|
||||
.. _Rockwell Automation Publication 1756-PM020-EN-P - November 2012: http://literature.rockwellautomation.com/idc/groups/literature/documents/pm/1756-pm020_-en-p.pdf
|
||||
|
||||
See the following snippet for communication with a Controllogix PLC:
|
||||
|
||||
::
|
||||
|
||||
from pycomm.ab_comm.clx import Driver as ClxDriver
|
||||
import logging
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(
|
||||
filename="ClxDriver.log",
|
||||
format="%(levelname)-10s %(asctime)s %(message)s",
|
||||
level=logging.DEBUG
|
||||
)
|
||||
c = ClxDriver()
|
||||
|
||||
if c.open('172.16.2.161'):
|
||||
|
||||
print(c.read_tag(['ControlWord']))
|
||||
print(c.read_tag(['parts', 'ControlWord', 'Counts']))
|
||||
|
||||
print(c.write_tag('Counts', -26, 'INT'))
|
||||
print(c.write_tag(('Counts', 26, 'INT')))
|
||||
print(c.write_tag([('Counts', 26, 'INT')]))
|
||||
print(c.write_tag([('Counts', -26, 'INT'), ('ControlWord', -30, 'DINT'), ('parts', 31, 'DINT')]))
|
||||
|
||||
# To read an array
|
||||
r_array = c.read_array("TotalCount", 1750)
|
||||
for tag in r_array:
|
||||
print (tag)
|
||||
|
||||
# reset tha array to all 0
|
||||
w_array = []
|
||||
for i in xrange(1750):
|
||||
w_array.append(0)
|
||||
c.write_array("TotalCount", "SINT", w_array)
|
||||
|
||||
c.close()
|
||||
|
||||
|
||||
|
||||
|
||||
See the following snippet for communication with a Micrologix PLC:
|
||||
|
||||
|
||||
::
|
||||
|
||||
from pycomm.ab_comm.slc import Driver as SlcDriver
|
||||
import logging
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
logging.basicConfig(
|
||||
filename="SlcDriver.log",
|
||||
format="%(levelname)-10s %(asctime)s %(message)s",
|
||||
level=logging.DEBUG
|
||||
)
|
||||
c = SlcDriver()
|
||||
if c.open('172.16.2.160'):
|
||||
|
||||
print c.read_tag('S:1/5')
|
||||
print c.read_tag('S:60', 2)
|
||||
|
||||
print c.write_tag('N7:0', [-30, 32767, -32767])
|
||||
print c.write_tag('N7:0', 21)
|
||||
print c.read_tag('N7:0', 10)
|
||||
|
||||
print c.write_tag('F8:0', [3.1, 4.95, -32.89])
|
||||
print c.write_tag('F8:0', 21)
|
||||
print c.read_tag('F8:0', 3)
|
||||
|
||||
print c.write_tag('B3:100', [23, -1, 4, 9])
|
||||
print c.write_tag('B3:100', 21)
|
||||
print c.read_tag('B3:100', 4)
|
||||
|
||||
print c.write_tag('T4:3.PRE', 431)
|
||||
print c.read_tag('T4:3.PRE')
|
||||
print c.write_tag('C5:0.PRE', 501)
|
||||
print c.read_tag('C5:0.PRE')
|
||||
print c.write_tag('T4:3.ACC', 432)
|
||||
print c.read_tag('T4:3.ACC')
|
||||
print c.write_tag('C5:0.ACC', 502)
|
||||
print c.read_tag('C5:0.ACC')
|
||||
|
||||
c.write_tag('T4:2.EN', 0)
|
||||
c.write_tag('T4:2.TT', 0)
|
||||
c.write_tag('T4:2.DN', 0)
|
||||
print c.read_tag('T4:2.EN', 1)
|
||||
print c.read_tag('T4:2.TT', 1)
|
||||
print c.read_tag('T4:2.DN',)
|
||||
|
||||
c.write_tag('C5:0.CU', 1)
|
||||
c.write_tag('C5:0.CD', 0)
|
||||
c.write_tag('C5:0.DN', 1)
|
||||
c.write_tag('C5:0.OV', 0)
|
||||
c.write_tag('C5:0.UN', 1)
|
||||
c.write_tag('C5:0.UA', 0)
|
||||
print c.read_tag('C5:0.CU')
|
||||
print c.read_tag('C5:0.CD')
|
||||
print c.read_tag('C5:0.DN')
|
||||
print c.read_tag('C5:0.OV')
|
||||
print c.read_tag('C5:0.UN')
|
||||
print c.read_tag('C5:0.UA')
|
||||
|
||||
c.write_tag('B3:100', 1)
|
||||
print c.read_tag('B3:100')
|
||||
|
||||
c.write_tag('B3/3955', 1)
|
||||
print c.read_tag('B3/3955')
|
||||
|
||||
c.write_tag('N7:0/2', 1)
|
||||
print c.read_tag('N7:0/2')
|
||||
|
||||
print c.write_tag('O:0.0/4', 1)
|
||||
print c.read_tag('O:0.0/4')
|
||||
|
||||
c.close()
|
||||
|
||||
|
||||
The Future
|
||||
~~~~~~~~~~
|
||||
This package is under development.
|
||||
The modules _ab_comm.clx_ and _ab_comm.slc_ are completed at moment but other drivers will be added in the future.
|
||||
|
||||
Thanks
|
||||
~~~~~~
|
||||
Thanks to patrickjmcd_ for the help with the Direct Connections and thanks in advance to anyone for feedback and suggestions.
|
||||
|
||||
.. _patrickjmcd: https://github.com/patrickjmcd
|
||||
|
||||
License
|
||||
~~~~~~~
|
||||
pycomm is distributed under the MIT License
|
||||
42
daq_sample/pycomm-master/examples/test_clx_comm.py
Executable file
42
daq_sample/pycomm-master/examples/test_clx_comm.py
Executable file
@@ -0,0 +1,42 @@
|
||||
from pycomm.ab_comm.clx import Driver as ClxDriver
|
||||
import logging
|
||||
|
||||
from time import sleep
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
logging.basicConfig(
|
||||
filename="ClxDriver.log",
|
||||
format="%(levelname)-10s %(asctime)s %(message)s",
|
||||
level=logging.DEBUG
|
||||
)
|
||||
c = ClxDriver()
|
||||
|
||||
print c['port']
|
||||
print c.__version__
|
||||
|
||||
|
||||
if c.open('172.16.2.161'):
|
||||
while 1:
|
||||
try:
|
||||
print(c.read_tag(['ControlWord']))
|
||||
print(c.read_tag(['parts', 'ControlWord', 'Counts']))
|
||||
|
||||
print(c.write_tag('Counts', -26, 'INT'))
|
||||
print(c.write_tag(('Counts', 26, 'INT')))
|
||||
print(c.write_tag([('Counts', 26, 'INT')]))
|
||||
print(c.write_tag([('Counts', -26, 'INT'), ('ControlWord', -30, 'DINT'), ('parts', 31, 'DINT')]))
|
||||
sleep(1)
|
||||
except Exception as e:
|
||||
err = c.get_status()
|
||||
c.close()
|
||||
print err
|
||||
pass
|
||||
|
||||
# To read an array
|
||||
r_array = c.read_array("TotalCount", 1750)
|
||||
for tag in r_array:
|
||||
print (tag)
|
||||
|
||||
c.close()
|
||||
72
daq_sample/pycomm-master/examples/test_slc_only.py
Executable file
72
daq_sample/pycomm-master/examples/test_slc_only.py
Executable file
@@ -0,0 +1,72 @@
|
||||
__author__ = 'agostino'
|
||||
|
||||
from pycomm.ab_comm.slc import Driver as SlcDriver
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
c = SlcDriver(True, 'delete_slc.log')
|
||||
if c.open('172.16.2.160'):
|
||||
|
||||
while 1:
|
||||
try:
|
||||
print c.read_tag('S:1/5')
|
||||
print c.read_tag('S:60', 2)
|
||||
|
||||
print c.write_tag('N7:0', [-30, 32767, -32767])
|
||||
print c.write_tag('N7:0', 21)
|
||||
print c.read_tag('N7:0', 10)
|
||||
|
||||
print c.write_tag('F8:0', [3.1, 4.95, -32.89])
|
||||
print c.write_tag('F8:0', 21)
|
||||
print c.read_tag('F8:0', 3)
|
||||
|
||||
print c.write_tag('B3:100', [23, -1, 4, 9])
|
||||
print c.write_tag('B3:100', 21)
|
||||
print c.read_tag('B3:100', 4)
|
||||
|
||||
print c.write_tag('T4:3.PRE', 431)
|
||||
print c.read_tag('T4:3.PRE')
|
||||
print c.write_tag('C5:0.PRE', 501)
|
||||
print c.read_tag('C5:0.PRE')
|
||||
print c.write_tag('T4:3.ACC', 432)
|
||||
print c.read_tag('T4:3.ACC')
|
||||
print c.write_tag('C5:0.ACC', 502)
|
||||
print c.read_tag('C5:0.ACC')
|
||||
|
||||
c.write_tag('T4:2.EN', 0)
|
||||
c.write_tag('T4:2.TT', 0)
|
||||
c.write_tag('T4:2.DN', 0)
|
||||
print c.read_tag('T4:2.EN', 1)
|
||||
print c.read_tag('T4:2.TT', 1)
|
||||
print c.read_tag('T4:2.DN',)
|
||||
|
||||
c.write_tag('C5:0.CU', 1)
|
||||
c.write_tag('C5:0.CD', 0)
|
||||
c.write_tag('C5:0.DN', 1)
|
||||
c.write_tag('C5:0.OV', 0)
|
||||
c.write_tag('C5:0.UN', 1)
|
||||
c.write_tag('C5:0.UA', 0)
|
||||
print c.read_tag('C5:0.CU')
|
||||
print c.read_tag('C5:0.CD')
|
||||
print c.read_tag('C5:0.DN')
|
||||
print c.read_tag('C5:0.OV')
|
||||
print c.read_tag('C5:0.UN')
|
||||
print c.read_tag('C5:0.UA')
|
||||
|
||||
c.write_tag('B3:100', 1)
|
||||
print c.read_tag('B3:100')
|
||||
|
||||
c.write_tag('B3/3955', 1)
|
||||
print c.read_tag('B3/3955')
|
||||
|
||||
c.write_tag('N7:0/2', 1)
|
||||
print c.read_tag('N7:0/2')
|
||||
|
||||
print c.write_tag('O:0.0/4', 1)
|
||||
print c.read_tag('O:0.0/4')
|
||||
except Exception as e:
|
||||
err = c.get_status()
|
||||
#c.close()
|
||||
print err
|
||||
pass
|
||||
c.close()
|
||||
0
daq/tag/micro800/pycomm_micro/__init__.py → daq_sample/pycomm-master/pycomm/__init__.py
Normal file → Executable file
0
daq/tag/micro800/pycomm_micro/__init__.py → daq_sample/pycomm-master/pycomm/__init__.py
Normal file → Executable file
0
daq/tag/micro800/pycomm_micro/ab_comm/__init__.py → daq_sample/pycomm-master/pycomm/ab_comm/__init__.py
Normal file → Executable file
0
daq/tag/micro800/pycomm_micro/ab_comm/__init__.py → daq_sample/pycomm-master/pycomm/ab_comm/__init__.py
Normal file → Executable file
118
daq/tag/micro800/pycomm_micro/ab_comm/clx.py → daq_sample/pycomm-master/pycomm/ab_comm/clx.py
Normal file → Executable file
118
daq/tag/micro800/pycomm_micro/ab_comm/clx.py → daq_sample/pycomm-master/pycomm/ab_comm/clx.py
Normal file → Executable file
@@ -23,9 +23,17 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
from tag.micro800.pycomm_micro.cip.cip_base import *
|
||||
from tag.micro800.pycomm_micro.common import setup_logger
|
||||
from pycomm.cip.cip_base import *
|
||||
import logging
|
||||
try: # Python 2.7+
|
||||
from logging import NullHandler
|
||||
except ImportError:
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.addHandler(NullHandler())
|
||||
|
||||
|
||||
class Driver(Base):
|
||||
@@ -47,11 +55,9 @@ class Driver(Base):
|
||||
- ControlLogix 5572 and 1756-EN2T Module
|
||||
|
||||
"""
|
||||
def __init__(self, debug=False, filename=None):
|
||||
if debug:
|
||||
super(Driver, self).__init__(setup_logger('ab_comm.clx', logging.DEBUG, filename))
|
||||
else:
|
||||
super(Driver, self).__init__(setup_logger('ab_comm.clx', logging.INFO, filename))
|
||||
|
||||
def __init__(self):
|
||||
super(Driver, self).__init__()
|
||||
|
||||
self._buffer = {}
|
||||
self._get_template_in_progress = False
|
||||
@@ -176,7 +182,7 @@ class Driver(Base):
|
||||
self._byte_offset += bytes_received
|
||||
else:
|
||||
self._status = (1, 'unknown status {0} during _parse_template'.format(status))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
self._last_instance = -1
|
||||
|
||||
def _parse_fragment(self, start_ptr, status):
|
||||
@@ -197,12 +203,18 @@ class Driver(Base):
|
||||
while idx < fragment_returned_length:
|
||||
try:
|
||||
typ = I_DATA_TYPE[data_type]
|
||||
value = UNPACK_DATA_FUNCTION[typ](fragment_returned[idx:idx+DATA_FUNCTION_SIZE[typ]])
|
||||
if self._output_raw:
|
||||
value = fragment_returned[idx:idx+DATA_FUNCTION_SIZE[typ]]
|
||||
else:
|
||||
value = UNPACK_DATA_FUNCTION[typ](fragment_returned[idx:idx+DATA_FUNCTION_SIZE[typ]])
|
||||
idx += DATA_FUNCTION_SIZE[typ]
|
||||
except Exception as e:
|
||||
raise DataError(e)
|
||||
self._tag_list.append((self._last_position, value))
|
||||
self._last_position += 1
|
||||
if self._output_raw:
|
||||
self._tag_list += value
|
||||
else:
|
||||
self._tag_list.append((self._last_position, value))
|
||||
self._last_position += 1
|
||||
|
||||
if status == SUCCESS:
|
||||
self._byte_offset = -1
|
||||
@@ -350,9 +362,9 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (6, "Target did not connected. read_tag will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. read_tag will not be executed.")
|
||||
# multi_requests = False
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. read_tag will not be executed.")
|
||||
|
||||
if multi_requests:
|
||||
rp_list = []
|
||||
for t in tag:
|
||||
@@ -393,13 +405,12 @@ class Driver(Base):
|
||||
else:
|
||||
# Get the data type
|
||||
data_type = unpack_uint(self._reply[50:52])
|
||||
# print I_DATA_TYPE[data_type]
|
||||
try:
|
||||
return UNPACK_DATA_FUNCTION[I_DATA_TYPE[data_type]](self._reply[52:]), I_DATA_TYPE[data_type]
|
||||
except Exception as e:
|
||||
raise DataError(e)
|
||||
|
||||
def read_array(self, tag, counts):
|
||||
def read_array(self, tag, counts, raw=False):
|
||||
""" read array of atomic data type from a connected plc
|
||||
|
||||
At the moment there is not a strong validation for the argument passed. The user should verify
|
||||
@@ -407,18 +418,23 @@ class Driver(Base):
|
||||
|
||||
:param tag: the name of the tag to read
|
||||
:param counts: the number of element to read
|
||||
:param raw: the value should output as raw-value (hex)
|
||||
:return: None is returned in case of error otherwise the tag list is returned
|
||||
"""
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (7, "Target did not connected. read_tag will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. read_tag will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. read_tag will not be executed.")
|
||||
|
||||
self._byte_offset = 0
|
||||
self._last_position = 0
|
||||
self._output_raw = raw
|
||||
|
||||
self._tag_list = []
|
||||
if self._output_raw:
|
||||
self._tag_list = ''
|
||||
else:
|
||||
self._tag_list = []
|
||||
while self._byte_offset != -1:
|
||||
rp = create_tag_rp(tag)
|
||||
if rp is None:
|
||||
@@ -480,8 +496,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (8, "Target did not connected. write_tag will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. write_tag will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. write_tag will not be executed.")
|
||||
|
||||
if multi_requests:
|
||||
rp_list = []
|
||||
@@ -525,7 +541,7 @@ class Driver(Base):
|
||||
rp = create_tag_rp(name)
|
||||
if rp is None:
|
||||
self._status = (8, "Cannot create tag {0} request packet. write_tag will not be executed.".format(tag))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
return None
|
||||
else:
|
||||
# Creating the Message Request Packet
|
||||
@@ -555,7 +571,7 @@ class Driver(Base):
|
||||
raise DataError("send_unit_data returned not valid data")
|
||||
return ret_val
|
||||
|
||||
def write_array(self, tag, data_type, values):
|
||||
def write_array(self, tag, data_type, values, raw=False):
|
||||
""" write array of atomic data type from a connected plc
|
||||
|
||||
At the moment there is not a strong validation for the argument passed. The user should verify
|
||||
@@ -563,25 +579,29 @@ class Driver(Base):
|
||||
|
||||
:param tag: the name of the tag to read
|
||||
:param data_type: the type of tag to write
|
||||
:param values: the array of values to write
|
||||
:param values: the array of values to write, if raw: the frame with bytes
|
||||
:param raw: indicates that the values are given as raw values (hex)
|
||||
"""
|
||||
if not isinstance(values, list):
|
||||
self._status = (9, "A list of tags must be passed to write_array.")
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("A list of tags must be passed to write_array.")
|
||||
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (9, "Target did not connected. write_array will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. write_array will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. write_array will not be executed.")
|
||||
|
||||
array_of_values = ""
|
||||
byte_size = 0
|
||||
byte_offset = 0
|
||||
|
||||
for i, value in enumerate(values):
|
||||
array_of_values += PACK_DATA_FUNCTION[data_type](value)
|
||||
if raw:
|
||||
array_of_values += value
|
||||
else:
|
||||
array_of_values += PACK_DATA_FUNCTION[data_type](value)
|
||||
byte_size += DATA_FUNCTION_SIZE[data_type]
|
||||
|
||||
if byte_size >= 450 or i == len(values)-1:
|
||||
@@ -626,8 +646,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (10, "Target did not connected. get_tag_list will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. get_tag_list will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. get_tag_list will not be executed.")
|
||||
|
||||
self._last_instance = 0
|
||||
|
||||
@@ -674,8 +694,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (10, "Target did not connected. get_tag_list will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. get_tag_list will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. get_tag_list will not be executed.")
|
||||
|
||||
message_request = [
|
||||
pack_uint(self._get_sequence()),
|
||||
@@ -708,8 +728,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (10, "Target did not connected. get_tag_list will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. get_tag_list will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. get_tag_list will not be executed.")
|
||||
|
||||
self._byte_offset = 0
|
||||
self._buffer = ""
|
||||
@@ -753,10 +773,10 @@ class Driver(Base):
|
||||
continue
|
||||
if tag['symbol_type'] & 0b0001000000000000:
|
||||
continue
|
||||
dimension = tag['symbol_type'] & 0b0110000000000000 >> 13
|
||||
template_instance_id = tag['symbol_type'] & 0b0000111111111111
|
||||
dimension = (tag['symbol_type'] & 0b0110000000000000) >> 13
|
||||
|
||||
if tag['symbol_type'] & 0b1000000000000000 :
|
||||
template_instance_id = tag['symbol_type'] & 0b0000111111111111
|
||||
tag_type = 'struct'
|
||||
data_type = 'user-created'
|
||||
self._tag_list.append({'instance_id': tag['instance_id'],
|
||||
@@ -769,12 +789,22 @@ class Driver(Base):
|
||||
'udt': {}})
|
||||
else:
|
||||
tag_type = 'atomic'
|
||||
data_type = I_DATA_TYPE[template_instance_id]
|
||||
self._tag_list.append({'instance_id': tag['instance_id'],
|
||||
'tag_name': tag['tag_name'],
|
||||
'dim': dimension,
|
||||
'tag_type': tag_type,
|
||||
'data_type': data_type})
|
||||
datatype = tag['symbol_type'] & 0b0000000011111111
|
||||
data_type = I_DATA_TYPE[datatype]
|
||||
if datatype == 0xc1:
|
||||
bit_position = (tag['symbol_type'] & 0b0000011100000000) >> 8
|
||||
self._tag_list.append({'instance_id': tag['instance_id'],
|
||||
'tag_name': tag['tag_name'],
|
||||
'dim': dimension,
|
||||
'tag_type': tag_type,
|
||||
'data_type': data_type,
|
||||
'bit_position' : bit_position})
|
||||
else:
|
||||
self._tag_list.append({'instance_id': tag['instance_id'],
|
||||
'tag_name': tag['tag_name'],
|
||||
'dim': dimension,
|
||||
'tag_type': tag_type,
|
||||
'data_type': data_type})
|
||||
except Exception as e:
|
||||
raise DataError(e)
|
||||
|
||||
@@ -841,7 +871,3 @@ class Driver(Base):
|
||||
# Step 4
|
||||
|
||||
return self._tag_list
|
||||
|
||||
|
||||
|
||||
|
||||
178
daq/tag/micro800/pycomm_micro/ab_comm/slc.py → daq_sample/pycomm-master/pycomm/ab_comm/slc.py
Normal file → Executable file
178
daq/tag/micro800/pycomm_micro/ab_comm/slc.py → daq_sample/pycomm-master/pycomm/ab_comm/slc.py
Normal file → Executable file
@@ -23,11 +23,21 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
from tag.micro800.pycomm_micro.cip.cip_base import *
|
||||
from tag.micro800.pycomm_micro.common import setup_logger
|
||||
from pycomm.cip.cip_base import *
|
||||
import re
|
||||
import logging
|
||||
import math
|
||||
#import binascii
|
||||
|
||||
import logging
|
||||
try: # Python 2.7+
|
||||
from logging import NullHandler
|
||||
except ImportError:
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.addHandler(NullHandler())
|
||||
|
||||
|
||||
def parse_tag(tag):
|
||||
@@ -45,7 +55,7 @@ def parse_tag(tag):
|
||||
'write_func': '\xab',
|
||||
'address_field': 3}
|
||||
|
||||
t = re.search(r"(?P<file_type>[FBN])(?P<file_number>\d{1,3})"
|
||||
t = re.search(r"(?P<file_type>[LFBN])(?P<file_number>\d{1,3})"
|
||||
r"(:)(?P<element_number>\d{1,3})"
|
||||
r"(/(?P<sub_element>\d{1,2}))?",
|
||||
tag, flags=re.IGNORECASE)
|
||||
@@ -148,11 +158,8 @@ class Driver(Base):
|
||||
"""
|
||||
SLC/PLC_5 Implementation
|
||||
"""
|
||||
def __init__(self, debug=False, filename=None):
|
||||
if debug:
|
||||
super(Driver, self).__init__(setup_logger('ab_comm.slc', logging.DEBUG, filename))
|
||||
else:
|
||||
super(Driver, self).__init__(setup_logger('ab_comm.slc', logging.INFO, filename))
|
||||
def __init__(self):
|
||||
super(Driver, self).__init__()
|
||||
|
||||
self.__version__ = '0.1'
|
||||
self._last_sequence = 0
|
||||
@@ -207,6 +214,127 @@ class Driver(Base):
|
||||
except Exception as e:
|
||||
raise DataError(e)
|
||||
|
||||
def __queue_data_available(self, queue_number):
|
||||
""" read the queue
|
||||
|
||||
Possible combination can be passed to this method:
|
||||
print c.read_tag('F8:0', 3) return a list of 3 registers starting from F8:0
|
||||
print c.read_tag('F8:0') return one value
|
||||
|
||||
It is possible to read status bit
|
||||
|
||||
:return: None is returned in case of error
|
||||
"""
|
||||
|
||||
# Creating the Message Request Packet
|
||||
self._last_sequence = pack_uint(Base._get_sequence())
|
||||
|
||||
# PCCC_Cmd_Rd_w3_Q2 = [0x0f, 0x00, 0x30, 0x00, 0xa2, 0x6d, 0x00, 0xa5, 0x02, 0x00]
|
||||
message_request = [
|
||||
self._last_sequence,
|
||||
'\x4b',
|
||||
'\x02',
|
||||
CLASS_ID["8-bit"],
|
||||
PATH["PCCC"],
|
||||
'\x07',
|
||||
self.attribs['vid'],
|
||||
self.attribs['vsn'],
|
||||
'\x0f',
|
||||
'\x00',
|
||||
self._last_sequence[1],
|
||||
self._last_sequence[0],
|
||||
'\xa2', # protected typed logical read with three address fields FNC
|
||||
'\x6d', # Byte size to read = 109
|
||||
'\x00', # File Number
|
||||
'\xa5', # File Type
|
||||
pack_uint(queue_number)
|
||||
]
|
||||
|
||||
if self.send_unit_data(
|
||||
build_common_packet_format(
|
||||
DATA_ITEM['Connected'],
|
||||
''.join(message_request),
|
||||
ADDRESS_ITEM['Connection Based'],
|
||||
addr_data=self._target_cid,)):
|
||||
|
||||
sts = int(unpack_uint(self._reply[2:4]))
|
||||
if sts == 146:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
raise DataError("read_queue [send_unit_data] returned not valid data")
|
||||
|
||||
def __save_record(self, filename):
|
||||
with open(filename, "a") as csv_file:
|
||||
logger.debug("SLC __save_record read:{0}".format(self._reply[61:]))
|
||||
csv_file.write(self._reply[61:]+'\n')
|
||||
csv_file.close()
|
||||
|
||||
def __get_queue_size(self, queue_number):
|
||||
""" get queue size
|
||||
"""
|
||||
# Creating the Message Request Packet
|
||||
self._last_sequence = pack_uint(Base._get_sequence())
|
||||
|
||||
message_request = [
|
||||
self._last_sequence,
|
||||
'\x4b',
|
||||
'\x02',
|
||||
CLASS_ID["8-bit"],
|
||||
PATH["PCCC"],
|
||||
'\x07',
|
||||
self.attribs['vid'],
|
||||
self.attribs['vsn'],
|
||||
'\x0f',
|
||||
'\x00',
|
||||
self._last_sequence[1],
|
||||
self._last_sequence[0],
|
||||
# '\x30',
|
||||
# '\x00',
|
||||
'\xa1', # FNC to get the queue size
|
||||
'\x06', # Byte size to read = 06
|
||||
'\x00', # File Number
|
||||
'\xea', # File Type ????
|
||||
'\xff', # File Type ????
|
||||
pack_uint(queue_number)
|
||||
]
|
||||
|
||||
if self.send_unit_data(
|
||||
build_common_packet_format(
|
||||
DATA_ITEM['Connected'],
|
||||
''.join(message_request),
|
||||
ADDRESS_ITEM['Connection Based'],
|
||||
addr_data=self._target_cid,)):
|
||||
sts = int(unpack_uint(self._reply[65:67]))
|
||||
logger.debug("SLC __get_queue_size({0}) returned {1}".format(queue_number, sts))
|
||||
return sts
|
||||
else:
|
||||
raise DataError("read_queue [send_unit_data] returned not valid data")
|
||||
|
||||
def read_queue(self, queue_number, file_name):
|
||||
""" read the queue
|
||||
|
||||
"""
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (5, "Target did not connected. is_queue_available will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. is_queue_available will not be executed.")
|
||||
|
||||
if self.__queue_data_available(queue_number):
|
||||
logger.debug("SLC read_queue: Queue {0} has data".format(queue_number))
|
||||
self.__save_record(file_name + str(queue_number) + ".csv")
|
||||
size = self.__get_queue_size(queue_number)
|
||||
if size > 0:
|
||||
for i in range(0, size):
|
||||
if self.__queue_data_available(queue_number):
|
||||
self.__save_record(file_name + str(queue_number) + ".csv")
|
||||
|
||||
logger.debug("SLC read_queue: {0} record extract from queue {1}".format(size, queue_number))
|
||||
else:
|
||||
logger.debug("SLC read_queue: Queue {0} has no data".format(queue_number))
|
||||
|
||||
def read_tag(self, tag, n=1):
|
||||
""" read tag from a connected plc
|
||||
|
||||
@@ -221,7 +349,7 @@ class Driver(Base):
|
||||
res = parse_tag(tag)
|
||||
if not res[0]:
|
||||
self._status = (1000, "Error parsing the tag passed to read_tag({0},{1})".format(tag, n))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error parsing the tag passed to read_tag({0},{1})".format(tag, n))
|
||||
|
||||
bit_read = False
|
||||
@@ -234,8 +362,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (5, "Target did not connected. read_tag will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. read_tag will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. read_tag will not be executed.")
|
||||
|
||||
data_size = PCCC_DATA_SIZE[res[2]['file_type']]
|
||||
|
||||
@@ -263,7 +391,7 @@ class Driver(Base):
|
||||
pack_usint(sub_element)
|
||||
]
|
||||
|
||||
self.logger.debug("SLC read_tag({0},{1})".format(tag, n))
|
||||
logger.debug("SLC read_tag({0},{1})".format(tag, n))
|
||||
if self.send_unit_data(
|
||||
build_common_packet_format(
|
||||
DATA_ITEM['Connected'],
|
||||
@@ -275,7 +403,7 @@ class Driver(Base):
|
||||
if sts != 0:
|
||||
sts_txt = PCCC_ERROR_CODE[sts]
|
||||
self._status = (1000, "Error({0}) returned from read_tag({1},{2})".format(sts_txt, tag, n))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error({0}) returned from read_tag({1},{2})".format(sts_txt, tag, n))
|
||||
|
||||
new_value = 61
|
||||
@@ -307,7 +435,7 @@ class Driver(Base):
|
||||
|
||||
except Exception as e:
|
||||
self._status = (1000, "Error({0}) parsing the data returned from read_tag({1},{2})".format(e, tag, n))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error({0}) parsing the data returned from read_tag({1},{2})".format(e, tag, n))
|
||||
else:
|
||||
raise DataError("send_unit_data returned not valid data")
|
||||
@@ -327,17 +455,17 @@ class Driver(Base):
|
||||
res = parse_tag(tag)
|
||||
if not res[0]:
|
||||
self._status = (1000, "Error parsing the tag passed to read_tag({0},{1})".format(tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error parsing the tag passed to read_tag({0},{1})".format(tag, value))
|
||||
|
||||
if isinstance(value, list) and int(res[2]['address_field'] == 3):
|
||||
self._status = (1000, "Function's parameters error. read_tag({0},{1})".format(tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Function's parameters error. read_tag({0},{1})".format(tag, value))
|
||||
|
||||
if isinstance(value, list) and int(res[2]['address_field'] == 3):
|
||||
self._status = (1000, "Function's parameters error. read_tag({0},{1})".format(tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Function's parameters error. read_tag({0},{1})".format(tag, value))
|
||||
|
||||
bit_field = False
|
||||
@@ -357,8 +485,8 @@ class Driver(Base):
|
||||
if not self._target_is_connected:
|
||||
if not self.forward_open():
|
||||
self._status = (1000, "Target did not connected. write_tag will not be executed.")
|
||||
self.logger.warning(self._status)
|
||||
raise Error("Target did not connected. write_tag will not be executed.")
|
||||
logger.warning(self._status)
|
||||
raise DataError("Target did not connected. write_tag will not be executed.")
|
||||
|
||||
try:
|
||||
n = 0
|
||||
@@ -390,7 +518,7 @@ class Driver(Base):
|
||||
except Exception as e:
|
||||
self._status = (1000, "Error({0}) packing the values to write to the"
|
||||
"SLC write_tag({1},{2})".format(e, tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error({0}) packing the values to write to the "
|
||||
"SLC write_tag({1},{2})".format(e, tag, value))
|
||||
|
||||
@@ -420,7 +548,7 @@ class Driver(Base):
|
||||
pack_usint(sub_element)
|
||||
]
|
||||
|
||||
self.logger.debug("SLC write_tag({0},{1})".format(tag, value))
|
||||
logger.debug("SLC write_tag({0},{1})".format(tag, value))
|
||||
if self.send_unit_data(
|
||||
build_common_packet_format(
|
||||
DATA_ITEM['Connected'],
|
||||
@@ -432,15 +560,15 @@ class Driver(Base):
|
||||
if sts != 0:
|
||||
sts_txt = PCCC_ERROR_CODE[sts]
|
||||
self._status = (1000, "Error({0}) returned from SLC write_tag({1},{2})".format(sts_txt, tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error({0}) returned from SLC write_tag({1},{2})".format(sts_txt, tag, value))
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
self._status = (1000, "Error({0}) parsing the data returned from "
|
||||
"SLC write_tag({1},{2})".format(e, tag, value))
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
raise DataError("Error({0}) parsing the data returned from "
|
||||
"SLC write_tag({1},{2})".format(e, tag, value))
|
||||
else:
|
||||
raise DataError("send_unit_data returned not valid data")
|
||||
raise DataError("send_unit_data returned not valid data")
|
||||
0
daq/tag/micro800/pycomm_micro/cip/__init__.py → daq_sample/pycomm-master/pycomm/cip/__init__.py
Normal file → Executable file
0
daq/tag/micro800/pycomm_micro/cip/__init__.py → daq_sample/pycomm-master/pycomm/cip/__init__.py
Normal file → Executable file
113
daq/tag/micro800/pycomm_micro/cip/cip_base.py → daq_sample/pycomm-master/pycomm/cip/cip_base.py
Normal file → Executable file
113
daq/tag/micro800/pycomm_micro/cip/cip_base.py → daq_sample/pycomm-master/pycomm/cip/cip_base.py
Normal file → Executable file
@@ -26,10 +26,22 @@
|
||||
|
||||
import struct
|
||||
import socket
|
||||
import random
|
||||
|
||||
from os import getpid
|
||||
from tag.micro800.pycomm_micro.cip.cip_const import *
|
||||
from tag.micro800.pycomm_micro.common import PycommError
|
||||
from pycomm.cip.cip_const import *
|
||||
from pycomm.common import PycommError
|
||||
|
||||
|
||||
import logging
|
||||
try: # Python 2.7+
|
||||
from logging import NullHandler
|
||||
except ImportError:
|
||||
class NullHandler(logging.Handler):
|
||||
def emit(self, record):
|
||||
pass
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.addHandler(NullHandler())
|
||||
|
||||
|
||||
class CommError(PycommError):
|
||||
@@ -55,7 +67,6 @@ def pack_int(n):
|
||||
|
||||
def pack_uint(n):
|
||||
"""pack 16 bit into 2 bytes little endian"""
|
||||
# print("N: {0}".format(n))
|
||||
return struct.pack('<H', n)
|
||||
|
||||
|
||||
@@ -75,9 +86,9 @@ def pack_lint(l):
|
||||
|
||||
|
||||
def unpack_bool(st):
|
||||
if int(struct.unpack('B', st[0])[0]) == 0:
|
||||
return 0
|
||||
return 1
|
||||
if not (int(struct.unpack('B', st[0])[0]) == 0):
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
def unpack_sint(st):
|
||||
@@ -107,9 +118,6 @@ def unpack_real(st):
|
||||
"""unpack 4 bytes little endian to int"""
|
||||
return float(struct.unpack('<f', st[0:4])[0])
|
||||
|
||||
def unpack_lreal(st):
|
||||
"""unpack 8 bytes little endian to int"""
|
||||
return float(struct.unpack('<f', st[0:8])[0])
|
||||
|
||||
def unpack_lint(st):
|
||||
"""unpack 4 bytes little endian to int"""
|
||||
@@ -126,10 +134,9 @@ PACK_DATA_FUNCTION = {
|
||||
'SINT': pack_sint, # Signed 8-bit integer
|
||||
'INT': pack_int, # Signed 16-bit integer
|
||||
'UINT': pack_uint, # Unsigned 16-bit integer
|
||||
'USINT': pack_usint, # Unsigned 8-bit integer
|
||||
'USINT': pack_usint, # Unsigned Byte Integer
|
||||
'DINT': pack_dint, # Signed 32-bit integer
|
||||
'REAL': pack_real, # 32-bit floating point
|
||||
'LREAL': pack_real, # 32-bit floating point
|
||||
'LINT': pack_lint,
|
||||
'BYTE': pack_sint, # byte string 8-bits
|
||||
'WORD': pack_uint, # byte string 16-bits
|
||||
@@ -142,12 +149,10 @@ UNPACK_DATA_FUNCTION = {
|
||||
'BOOL': unpack_bool,
|
||||
'SINT': unpack_sint, # Signed 8-bit integer
|
||||
'INT': unpack_int, # Signed 16-bit integer
|
||||
'UINT': unpack_uint, # Unsigned 16-bit
|
||||
'USINT': unpack_usint, # Unsigned 8-bit integer
|
||||
'UINT': unpack_uint, # Unsigned 16-bit integer
|
||||
'USINT': unpack_usint, # Unsigned Byte Integer
|
||||
'DINT': unpack_dint, # Signed 32-bit integer
|
||||
'UDINT': unpack_dint, # Signed 32-bit integer
|
||||
'REAL': unpack_real, # 32-bit floating point,
|
||||
'LREAL': unpack_lreal, # 32-bit floating point,
|
||||
'LINT': unpack_lint,
|
||||
'BYTE': unpack_sint, # byte string 8-bits
|
||||
'WORD': unpack_uint, # byte string 16-bits
|
||||
@@ -159,6 +164,7 @@ UNPACK_DATA_FUNCTION = {
|
||||
DATA_FUNCTION_SIZE = {
|
||||
'BOOL': 1,
|
||||
'SINT': 1, # Signed 8-bit integer
|
||||
'USINT': 1, # Unisgned 8-bit integer
|
||||
'INT': 2, # Signed 16-bit integer
|
||||
'UINT': 2, # Unsigned 16-bit integer
|
||||
'DINT': 4, # Signed 32-bit integer
|
||||
@@ -196,7 +202,6 @@ PACK_PCCC_DATA_FUNCTION = {
|
||||
'I': pack_int
|
||||
}
|
||||
|
||||
|
||||
def print_bytes_line(msg):
|
||||
out = ''
|
||||
for ch in msg:
|
||||
@@ -474,15 +479,15 @@ class Base(object):
|
||||
_sequence = 0
|
||||
|
||||
|
||||
def __init__(self, logging):
|
||||
def __init__(self):
|
||||
if Base._sequence == 0:
|
||||
Base._sequence = getpid()
|
||||
else:
|
||||
Base._sequence = Base._get_sequence()
|
||||
|
||||
self.logger = logging
|
||||
self.__version__ = '0.1'
|
||||
self.__version__ = '0.3'
|
||||
self.__sock = None
|
||||
self.__direct_connections = False
|
||||
self._session = 0
|
||||
self._connection_opened = False
|
||||
self._reply = None
|
||||
@@ -499,12 +504,10 @@ class Base(object):
|
||||
self._last_tag_read = ()
|
||||
self._last_tag_write = ()
|
||||
self._status = (0, "")
|
||||
self._output_raw = False # indicating value should be output as raw (hex)
|
||||
|
||||
# self.attribs = {'context': '_pycomm_', 'protocol version': 1, 'rpi': 5000, 'port': 0xAF12, 'timeout': 10,
|
||||
# 'backplane': 1, 'cpu slot': 0, 'option': 0, 'cid': '\x27\x04\x19\x71', 'csn': '\x27\x04',
|
||||
# 'vid': '\x09\x10', 'vsn': '\x09\x10\x19\x71', 'name': 'Base', 'ip address': None}
|
||||
self.attribs = {'context': '_pycomm_', 'protocol version': 1, 'rpi': 5000, 'port': 0xAF12, 'timeout': 10,
|
||||
'backplane': 0, 'cpu slot': 0, 'option': 0, 'cid': '\x27\x04\x19\x71', 'csn': '\x27\x04',
|
||||
'backplane': 1, 'cpu slot': 0, 'option': 0, 'cid': '\x27\x04\x19\x71', 'csn': '\x27\x04',
|
||||
'vid': '\x09\x10', 'vsn': '\x09\x10\x19\x71', 'name': 'Base', 'ip address': None}
|
||||
|
||||
def __len__(self):
|
||||
@@ -554,6 +557,10 @@ class Base(object):
|
||||
def __repr__(self):
|
||||
return self._device_description
|
||||
|
||||
def generate_cid(self):
|
||||
self.attribs['cid'] = '{0}{1}{2}{3}'.format(chr(random.randint(0, 255)), chr(random.randint(0, 255))
|
||||
, chr(random.randint(0, 255)), chr(random.randint(0, 255)))
|
||||
|
||||
def description(self):
|
||||
return self._device_description
|
||||
|
||||
@@ -646,11 +653,11 @@ class Base(object):
|
||||
self._receive()
|
||||
if self._check_reply():
|
||||
self._session = unpack_dint(self._reply[4:8])
|
||||
self.logger.debug("Session ={0} has been registered.".format(print_bytes_line(self._reply[4:8])))
|
||||
logger.debug("Session ={0} has been registered.".format(print_bytes_line(self._reply[4:8])))
|
||||
return self._session
|
||||
|
||||
self._status = 'Warning ! the session has not been registered.'
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
return None
|
||||
|
||||
def forward_open(self):
|
||||
@@ -686,7 +693,6 @@ class Base(object):
|
||||
pack_uint(CONNECTION_PARAMETER['Default']),
|
||||
TRANSPORT_CLASS, # Transport Class
|
||||
# CONNECTION_SIZE['Backplane'],
|
||||
CONNECTION_SIZE['Direct Network'],
|
||||
# pack_usint(self.attribs['backplane']),
|
||||
# pack_usint(self.attribs['cpu slot']),
|
||||
CLASS_ID["8-bit"],
|
||||
@@ -694,6 +700,18 @@ class Base(object):
|
||||
INSTANCE_ID["8-bit"],
|
||||
pack_usint(1)
|
||||
]
|
||||
|
||||
if self.__direct_connections:
|
||||
forward_open_msg[20:1] = [
|
||||
CONNECTION_SIZE['Direct Network'],
|
||||
]
|
||||
else:
|
||||
forward_open_msg[20:3] = [
|
||||
CONNECTION_SIZE['Backplane'],
|
||||
pack_usint(self.attribs['backplane']),
|
||||
pack_usint(self.attribs['cpu slot'])
|
||||
]
|
||||
|
||||
if self.send_rr_data(
|
||||
build_common_packet_format(DATA_ITEM['Unconnected'], ''.join(forward_open_msg), ADDRESS_ITEM['UCMM'],)):
|
||||
self._target_cid = self._reply[44:48]
|
||||
@@ -714,7 +732,7 @@ class Base(object):
|
||||
if self._session == 0:
|
||||
self._status = (5, "A session need to be registered before to call forward_close.")
|
||||
raise CommError("A session need to be registered before to call forward_close.")
|
||||
# print ("Backplane:{0}\nCPU:{1}".format(self.attribs['backplane'], self.attribs['cpu slot']))
|
||||
|
||||
forward_close_msg = [
|
||||
FORWARD_CLOSE,
|
||||
pack_usint(2),
|
||||
@@ -727,9 +745,8 @@ class Base(object):
|
||||
self.attribs['csn'],
|
||||
self.attribs['vid'],
|
||||
self.attribs['vsn'],
|
||||
CONNECTION_SIZE['Direct Network'],
|
||||
# CONNECTION_SIZE['Backplane'],
|
||||
'\x00', # Reserved
|
||||
# '\x00', # Reserved
|
||||
# pack_usint(self.attribs['backplane']),
|
||||
# pack_usint(self.attribs['cpu slot']),
|
||||
CLASS_ID["8-bit"],
|
||||
@@ -737,12 +754,26 @@ class Base(object):
|
||||
INSTANCE_ID["8-bit"],
|
||||
pack_usint(1)
|
||||
]
|
||||
|
||||
if self.__direct_connections:
|
||||
forward_close_msg[11:2] = [
|
||||
CONNECTION_SIZE['Direct Network'],
|
||||
'\x00'
|
||||
]
|
||||
else:
|
||||
forward_close_msg[11:4] = [
|
||||
CONNECTION_SIZE['Backplane'],
|
||||
'\x00',
|
||||
pack_usint(self.attribs['backplane']),
|
||||
pack_usint(self.attribs['cpu slot'])
|
||||
]
|
||||
|
||||
if self.send_rr_data(
|
||||
build_common_packet_format(DATA_ITEM['Unconnected'], ''.join(forward_close_msg), ADDRESS_ITEM['UCMM'])):
|
||||
self._target_is_connected = False
|
||||
return True
|
||||
self._status = (5, "forward_close returned False")
|
||||
self.logger.warning(self._status)
|
||||
logger.warning(self._status)
|
||||
return False
|
||||
|
||||
def un_register_session(self):
|
||||
@@ -759,10 +790,10 @@ class Base(object):
|
||||
:return: true if no error otherwise false
|
||||
"""
|
||||
try:
|
||||
self.logger.debug(print_bytes_msg(self._message, '-------------- SEND --------------'))
|
||||
logger.debug(print_bytes_msg(self._message, '-------------- SEND --------------'))
|
||||
self.__sock.send(self._message)
|
||||
except Exception as e:
|
||||
#self.clean_up()
|
||||
# self.clean_up()
|
||||
raise CommError(e)
|
||||
|
||||
def _receive(self):
|
||||
@@ -772,18 +803,21 @@ class Base(object):
|
||||
"""
|
||||
try:
|
||||
self._reply = self.__sock.receive()
|
||||
self.logger.debug(print_bytes_msg(self._reply, '----------- RECEIVE -----------'))
|
||||
logger.debug(print_bytes_msg(self._reply, '----------- RECEIVE -----------'))
|
||||
except Exception as e:
|
||||
#self.clean_up()
|
||||
# self.clean_up()
|
||||
raise CommError(e)
|
||||
|
||||
def open(self, ip_address):
|
||||
def open(self, ip_address, direct_connection=False):
|
||||
"""
|
||||
socket open
|
||||
:param: ip address to connect to and type of connection. By default direct connection is disabled
|
||||
:return: true if no error otherwise false
|
||||
"""
|
||||
# handle the socket layer
|
||||
# set type of connection needed
|
||||
self.__direct_connections = direct_connection
|
||||
|
||||
# handle the socket layer
|
||||
if not self._connection_opened:
|
||||
try:
|
||||
if self.__sock is None:
|
||||
@@ -791,13 +825,16 @@ class Base(object):
|
||||
self.__sock.connect(ip_address, self.attribs['port'])
|
||||
self._connection_opened = True
|
||||
self.attribs['ip address'] = ip_address
|
||||
self.generate_cid()
|
||||
if self.register_session() is None:
|
||||
self._status = (13, "Session not registered")
|
||||
return False
|
||||
|
||||
# not sure but maybe I can remove this because is used to clean up any previous unclosed connection
|
||||
self.forward_close()
|
||||
return True
|
||||
except Exception as e:
|
||||
#self.clean_up()
|
||||
# self.clean_up()
|
||||
raise CommError(e)
|
||||
|
||||
def close(self):
|
||||
@@ -824,4 +861,4 @@ class Base(object):
|
||||
self._connection_opened = False
|
||||
|
||||
def is_connected(self):
|
||||
return self._connection_opened
|
||||
return self._connection_opened
|
||||
1
daq/tag/micro800/pycomm_micro/cip/cip_const.py → daq_sample/pycomm-master/pycomm/cip/cip_const.py
Normal file → Executable file
1
daq/tag/micro800/pycomm_micro/cip/cip_const.py → daq_sample/pycomm-master/pycomm/cip/cip_const.py
Normal file → Executable file
@@ -435,6 +435,7 @@ PCCC_DATA_TYPE = {
|
||||
|
||||
PCCC_DATA_SIZE = {
|
||||
'N': 2,
|
||||
# 'L': 4,
|
||||
'B': 2,
|
||||
'T': 6,
|
||||
'C': 6,
|
||||
8
daq_sample/pycomm-master/pycomm/common.py
Executable file
8
daq_sample/pycomm-master/pycomm/common.py
Executable file
@@ -0,0 +1,8 @@
|
||||
__author__ = 'Agostino Ruscito'
|
||||
__version__ = "1.0.8"
|
||||
__date__ = "08 03 2015"
|
||||
|
||||
class PycommError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
37
daq_sample/pycomm-master/setup.py
Executable file
37
daq_sample/pycomm-master/setup.py
Executable file
@@ -0,0 +1,37 @@
|
||||
from distutils.core import setup
|
||||
from pycomm import common
|
||||
import os
|
||||
|
||||
|
||||
def read(file_name):
|
||||
return open(os.path.join(os.path.dirname(__file__), file_name)).read()
|
||||
|
||||
setup(
|
||||
name="pycomm",
|
||||
author="Agostino Ruscito",
|
||||
author_email="uscito@gmail.com",
|
||||
version=common.__version__,
|
||||
description="A PLC communication library for Python",
|
||||
long_description=read('README.rst'),
|
||||
license="MIT",
|
||||
url="https://github.com/ruscito/pycomm",
|
||||
packages=[
|
||||
"pycomm",
|
||||
"pycomm.ab_comm",
|
||||
"pycomm.cip"
|
||||
],
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
'Intended Audience :: Developers',
|
||||
'Natural Language :: English',
|
||||
'License :: OSI Approved :: MIT License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.6',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
],
|
||||
)
|
||||
1
daq_sample/pycomm_helper
Submodule
1
daq_sample/pycomm_helper
Submodule
Submodule daq_sample/pycomm_helper added at a3b6c088c5
@@ -7,7 +7,7 @@ Created on April 7, 2016
|
||||
@description: Continuously loops through a list of tags to store values from a PLC into a MySQL database
|
||||
'''
|
||||
|
||||
from tag.tag import Tag
|
||||
from pycomm_helper.tag import Tag
|
||||
import traceback
|
||||
import time
|
||||
import random
|
||||
@@ -15,7 +15,8 @@ import requests
|
||||
import json
|
||||
|
||||
# DEFAULTS
|
||||
web_address = "https://10.10.10.10:3000"
|
||||
db_address = "10.10.10.10:3000"
|
||||
db_url = "https://{}".format(db_address)
|
||||
scan_rate = 30 # seconds
|
||||
save_all = "test" # use True, False, or any string
|
||||
|
||||
@@ -57,11 +58,11 @@ tag_store = {}
|
||||
|
||||
|
||||
def main():
|
||||
global web_address, scan_rate, save_all
|
||||
global db_address, scan_rate, save_all
|
||||
try:
|
||||
# Get tags stored in database
|
||||
get_tag_request_data = {'where': '{"tag_class": 5}'}
|
||||
get_tag_request = requests.get('{}/tag'.format(web_address), params=get_tag_request_data, verify=False)
|
||||
get_tag_request = requests.get('{}/tag'.format(db_url), params=get_tag_request_data, verify=False)
|
||||
tags = json.loads(get_tag_request.text)
|
||||
except Exception as e:
|
||||
print("Error getting tags: {}".format(e))
|
||||
@@ -70,7 +71,7 @@ def main():
|
||||
|
||||
try:
|
||||
sr_req_data = 'where={"parameter": "scan_rate"}'
|
||||
sr_req = requests.get('{}/config?{}'.format(web_address, sr_req_data), verify=False)
|
||||
sr_req = requests.get('{}/config?{}'.format(db_url, sr_req_data), verify=False)
|
||||
sr_try = json.loads(sr_req.text)
|
||||
if len(sr_try) > 0:
|
||||
scan_rate = int(sr_try[0]['val'])
|
||||
@@ -80,7 +81,7 @@ def main():
|
||||
|
||||
try:
|
||||
sa_req_data = {"where": {"parameter": "save_all"}}
|
||||
sa_req = requests.get('{}/config'.format(web_address), params=sa_req_data, verify=False)
|
||||
sa_req = requests.get('{}/config'.format(db_url), params=sa_req_data, verify=False)
|
||||
sa_try = json.loads(sa_req.text)
|
||||
if len(sa_try) > 0:
|
||||
if sa_try[0]['val'].lower() == "true":
|
||||
@@ -93,7 +94,7 @@ def main():
|
||||
|
||||
for t in tags:
|
||||
# name, tag, db_id, data_type, change_threshold, guarantee_sec, mapFn=None, device_type='CLX', ip_address='192.168.1.10'):
|
||||
tag_store[t['name']] = Sample(t['name'], t['tag'], t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'])
|
||||
tag_store[t['name']] = Sample(t['name'], t['tag'], t['id'], t['data_type'], t['change_threshold'], t['guarantee_sec'], mapFn=t['map_function'], ip_address=t['deviceID']['address'], db_address=db_address)
|
||||
|
||||
while True:
|
||||
for tag in tag_store:
|
||||
23
web_db/Dockerfile.rpi
Normal file
23
web_db/Dockerfile.rpi
Normal file
@@ -0,0 +1,23 @@
|
||||
FROM hypriot/rpi-node:latest
|
||||
|
||||
RUN apt-get -y update && apt-get install -y apt-utils dialog vim git
|
||||
COPY mysql-install.sh /tmp/mysql-install.sh
|
||||
COPY taglogger_db_structure.sql /tmp/taglogger_db_structure.sql
|
||||
RUN chmod +x /tmp/mysql-install.sh && /tmp/mysql-install.sh
|
||||
|
||||
RUN mkdir /root/tag-logger
|
||||
COPY www /root/tag-logger/www
|
||||
|
||||
COPY startup.sh /root/startup.sh
|
||||
RUN chmod +x /root/startup.sh
|
||||
|
||||
RUN npm install -g bower pm2 sails --silent
|
||||
RUN cd /root/tag-logger/www && npm install && bower install --allow-root && cd /
|
||||
|
||||
RUN apt-get clean
|
||||
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
CMD '/root/startup.sh'
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user