Commit Iniziale
Porting del protocollo OSAI OPEN-M per la cattura di dati movimenti assi Icludere i file di cattura Wireshark per riferimento
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/.project
|
||||
/.pydevproject
|
||||
*.py[ocd]
|
||||
0
NasoScope/__init__.py
Normal file
0
NasoScope/__init__.py
Normal file
48
NasoScope/config.json
Normal file
48
NasoScope/config.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"version": "0.1c",
|
||||
"logFile": "D:\\Test\\Nasoscope.log",
|
||||
"logFormat": "%(asctime)s|%(levelname)-7s|%(funcName)-10s|%(lineno)-3d: %(message)-50s",
|
||||
"logTimeFormat": "%m-%d %H:%M:%S",
|
||||
"URL": "http://localhost:8081",
|
||||
"samplePeriod": 10,
|
||||
"loopPeriod": 0.5,
|
||||
"recordTime": 3600,
|
||||
"fileSaveTime": 360,
|
||||
"fileSaveDir": "D:\\Test\\Traces3015\\{}_CL3015HSD.{fType}",
|
||||
"fileType": "csv",
|
||||
"variables": [ {"deviceID":1,
|
||||
"name": "AsseX",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
},
|
||||
{"deviceID":2,
|
||||
"name": "AsseY",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
},
|
||||
{"deviceID":3,
|
||||
"name": "AsseZ",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
},
|
||||
{"deviceID":4,
|
||||
"name": "AsseC",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
},
|
||||
{"deviceID":5,
|
||||
"name": "AsseB",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
},
|
||||
{"deviceID":6,
|
||||
"name": "AsseXs",
|
||||
"codes": [1000,1002,1017,1021,1022,1038],
|
||||
"descr": ["ActualFeed","FollowingError","MeasuredPosition","CalculatedAcceleration","Jerk","ServoPoint"]
|
||||
}
|
||||
],
|
||||
"mqttHost": "192.168.10.81",
|
||||
"mqttPort": 1883,
|
||||
"mqttSend": "nasoscope/cnc2recorder",
|
||||
"mqttReceive": "nasoscope/recorder2cnc"
|
||||
}
|
||||
368
NasoScope/nasomain.py
Normal file
368
NasoScope/nasomain.py
Normal file
@@ -0,0 +1,368 @@
|
||||
'''
|
||||
Created on 5 set 2019
|
||||
|
||||
@author: Emanuele Trabattoni
|
||||
'''
|
||||
import sys
|
||||
import time
|
||||
import json
|
||||
import requests
|
||||
import xml.etree.ElementTree as xml
|
||||
import xml.dom.minidom as mini
|
||||
import dicttoxml, xmltodict
|
||||
import logging
|
||||
import copy
|
||||
import base64
|
||||
import struct
|
||||
import csv
|
||||
|
||||
from paho.mqtt import client
|
||||
from NasoScope import templates
|
||||
from paho.mqtt.client import connack_string
|
||||
|
||||
def buildBody():
|
||||
root = xml.Element("soap:Envelope", templates.XMLNS_ENV)
|
||||
body = xml.SubElement(root, "soap:Body")
|
||||
return root,body
|
||||
|
||||
def getInfo():
|
||||
root,body = buildBody()
|
||||
xml.SubElement(body, "GetHWKey", templates.COMMANDS["GetHWKey"]["attrib"])
|
||||
resp = sendRequest(xml.tostring(root, encoding='utf-8'))
|
||||
if resp:
|
||||
return readResponse(resp)
|
||||
else:
|
||||
return False
|
||||
pass
|
||||
|
||||
def setupOscope():
|
||||
tempVarmap = list()
|
||||
for var in settings["variables"]:
|
||||
tempVar = copy.copy(templates.COMMANDS["MonAddVariable"]["elem"])
|
||||
tempVar["VarDescr"]["DeviceID"] = var["deviceID"]
|
||||
tempVar["VarDescr"]["SamplingPeriod"] = settings["samplePeriod"]
|
||||
for cod in var["codes"]:
|
||||
root,body = buildBody()
|
||||
addVariable = xml.SubElement(body, "MonAddVariable", templates.COMMANDS["MonAddVariable"]["attrib"])
|
||||
tempVar["VarDescr"]["Code"] = cod
|
||||
tempVarDescr = str(dicttoxml.dicttoxml(tempVar,attr_type=False), encoding='utf-8')
|
||||
tempxml = xml.fromstring(tempVarDescr)
|
||||
addVariable.append(tempxml.find("ChannelID"))
|
||||
addVariable.append(tempxml.find("VarDescr"))
|
||||
resp = sendRequest(xml.tostring(root, encoding='utf-8'))
|
||||
if resp:
|
||||
resp = readResponse(resp)["MonAddVariable-R"]
|
||||
if int(resp["retval"]):
|
||||
newvar=(var["name"],cod,int(resp["VariableID"]))
|
||||
tempVarmap.append(newvar)
|
||||
LOGGER.debug("Aggingo la variabile-> {}"\
|
||||
.format(newvar))
|
||||
pass
|
||||
else:
|
||||
LOGGER.error("Non posso aggiungere la variabile-> {}"\
|
||||
.format(var))
|
||||
else:
|
||||
return False
|
||||
return tempVarmap
|
||||
|
||||
def openChannel():
|
||||
root,body = buildBody()
|
||||
opench=xml.SubElement(body, "MonOpenChannel", templates.COMMANDS["MonOpenChannel"]["attrib"])
|
||||
sync=xml.SubElement(opench, "Synchronized")
|
||||
sync.text = "false"
|
||||
resp = sendRequest(xml.tostring(root, encoding='utf-8'))
|
||||
if resp is not False:
|
||||
return readResponse(resp)
|
||||
else:
|
||||
return False
|
||||
pass
|
||||
|
||||
def closeChannel():
|
||||
root,body = buildBody()
|
||||
opench=xml.SubElement(body, "MonCloseChannel", templates.COMMANDS["MonCloseChannel"]["attrib"])
|
||||
sync=xml.SubElement(opench, "Synchronized")
|
||||
sync.text = "false"
|
||||
resp = sendRequest(xml.tostring(root, encoding='utf-8'))
|
||||
if resp is not False:
|
||||
return readResponse(resp)
|
||||
else:
|
||||
return False
|
||||
pass
|
||||
|
||||
|
||||
def startSampling(channelID='0'):
|
||||
root,body = buildBody()
|
||||
startS = xml.SubElement(body, "MonStartSampling", templates.COMMANDS["MonStartSampling"]["attrib"])
|
||||
chid = xml.SubElement(startS, "ChannelID")
|
||||
chid.text = channelID
|
||||
try:
|
||||
return readResponse(sendRequest(xml.tostring(root, encoding='utf-8')))
|
||||
except Exception as e:
|
||||
LOGGER.error("Non riesco a iniziare la cattura -> {}".format(e))
|
||||
|
||||
def stopSampling(channelID='0'):
|
||||
root,body = buildBody()
|
||||
stopS = xml.SubElement(body, "MonStopSampling", templates.COMMANDS["MonStopSampling"]["attrib"])
|
||||
chid = xml.SubElement(stopS, "ChannelID")
|
||||
chid.text = channelID
|
||||
try:
|
||||
return readResponse(sendRequest(xml.tostring(root, encoding='utf-8')))
|
||||
except Exception as e:
|
||||
LOGGER.error("Non riesco a fermare la cattura -> {}".format(e))
|
||||
|
||||
def collectSamples(varMap, channelID='0'):
|
||||
dataDict = {}
|
||||
for var in varMap: dataDict[var[templates.VAR_NAME]] = dict()
|
||||
for var in varMap:
|
||||
try:
|
||||
root,body = buildBody()
|
||||
getVariable = xml.SubElement(body, "MonGetVariableS", templates.COMMANDS["MonGetVariableS"]["attrib"])
|
||||
chid = xml.SubElement(getVariable, "ChannelID")
|
||||
chid.text = channelID
|
||||
varid = xml.SubElement(getVariable, "VariableID")
|
||||
varid.text = str(var[templates.VAR_ID])
|
||||
resp = sendRequest(xml.tostring(root, encoding='utf-8'))
|
||||
if resp is not False:
|
||||
resp = readResponse(resp)["MonGetVariableS-R"]
|
||||
if int(resp["retval"]) >=1 :
|
||||
if len(resp["DataBuffer"]):
|
||||
dataBuffer_raw = base64.b64decode(resp["DataBuffer"])
|
||||
timeBuffer_raw = base64.b64decode(resp["TimeBuffer"])
|
||||
nVals = int(len(dataBuffer_raw)/8)
|
||||
dataStruct = struct.Struct("{}d".format(nVals))
|
||||
timeStruct = struct.Struct("{}q".format(nVals))
|
||||
dataVal = dataStruct.unpack(dataBuffer_raw)
|
||||
timeVal = timeStruct.unpack(timeBuffer_raw)
|
||||
dataDict[var[templates.VAR_NAME]][var[templates.VAR_REG]]=list(zip(timeVal,dataVal))
|
||||
pass
|
||||
else:
|
||||
LOGGER.warning("Empty Buffer")
|
||||
return False
|
||||
pass
|
||||
else:
|
||||
return False
|
||||
except Exception as e:
|
||||
LOGGER.error("Eccezione inaspettata -> {}".format(e))
|
||||
return False
|
||||
return dataDict
|
||||
pass
|
||||
|
||||
def readResponse(r):
|
||||
responseData = r.find("SOAP-ENV:Body", templates.XMLNS_RESP)
|
||||
if responseData is not None:
|
||||
xmlstr = xml.tostring(responseData, encoding='utf-8')
|
||||
xmldict = xmltodict.parse(xmlstr, encoding='utf-8', process_namespaces=True)
|
||||
return remNameSpace(xmldict)["Body"]
|
||||
else:
|
||||
return False
|
||||
pass
|
||||
|
||||
def remNameSpace(d, sep=':'):
|
||||
rv=dict()
|
||||
for k,v in d.items():
|
||||
if isinstance(v, dict):
|
||||
rv[k.split(sep)[len(k.split(sep))-1]]=remNameSpace(v)
|
||||
else:
|
||||
rv[k.split(sep)[len(k.split(sep))-1]]=v
|
||||
return rv
|
||||
|
||||
def sendRequest(req):
|
||||
req = str(req,encoding='utf-8')
|
||||
pprinted = mini.parseString(req)
|
||||
LOGGER.debug("XML_REQUEST\n"+pprinted.toprettyxml(indent='\t'))
|
||||
try:
|
||||
xmlResponse = requests.post(settings['URL'],templates.XML_HEADER+req,headers=templates.HTTP_HEADER)
|
||||
pprinted = mini.parseString(xmlResponse.text)
|
||||
LOGGER.debug("XML_RESPONSE\n"+pprinted.toprettyxml(indent='\t'))
|
||||
return xml.fromstring(xmlResponse.text)
|
||||
except requests.exceptions.RequestException as e:
|
||||
LOGGER.error("Timeout Richiesta HTTP -> ".format(str(e)))
|
||||
return False
|
||||
|
||||
def saveSamples(s, fileName = None):
|
||||
if fileName is None:
|
||||
fileName = settings["fileSaveDir"].format(time.strftime("%Y%m%d-%H.%M.%S"), fType=settings["fileType"])
|
||||
with open(fileName, mode = 'w', newline='') as dataOut:
|
||||
LOGGER.info("Salvo i campioni dei precedenti {}s -> {}".format(settings["fileSaveTime"],fileName))
|
||||
if settings["fileType"] == "csv":
|
||||
h = ["{0}-{1}_TS;{0}-{1}".format(dev["name"],reg) for dev in settings["variables"] for reg in dev["descr"]]
|
||||
dataOut.write(";".join(h)+'\n')
|
||||
dataWriter = csv.writer(dataOut, delimiter=';', quoting=csv.QUOTE_NONE)
|
||||
dataWriter.writerows([[iii for ii in i for iii in ii] \
|
||||
for i in zip(*[s[dev["name"]][code] \
|
||||
for dev in settings["variables"] \
|
||||
for code in dev["codes"]])])
|
||||
elif settings["fileType"] == "json":
|
||||
dataOut.newline='\r\n'
|
||||
dataOut.write(json.dumps(s))
|
||||
pass
|
||||
|
||||
def onMessage(cli, userdata, msg):
|
||||
global stat
|
||||
msg=str(msg.payload)
|
||||
if "STOP" in msg:
|
||||
stat = "STOP"
|
||||
pass
|
||||
elif "PAUSE" in msg:
|
||||
pass
|
||||
elif "START" in msg:
|
||||
stat = "INI"
|
||||
pass
|
||||
elif "SAVE" in msg:
|
||||
saveSamples(samples)
|
||||
pass
|
||||
elif "EXIT" in msg:
|
||||
pass
|
||||
else:
|
||||
LOGGER.error("Messaggio MQTT sconosciuto")
|
||||
pass
|
||||
|
||||
def onConnect(cli, userdata, flags, rc):
|
||||
LOGGER.debug("Connessione a MQTT -> {}".format(connack_string(rc)))
|
||||
cli.publish(settings["mqttSend"],"CLIENT_ON")
|
||||
pass
|
||||
|
||||
def onDisconnect(cli, userdata, rc):
|
||||
LOGGER.warning("Disonnesso da MQTT -> {}".format(connack_string(rc)))
|
||||
cli.reconnect()
|
||||
pass
|
||||
|
||||
###################################
|
||||
############# MAIN ################
|
||||
###################################
|
||||
if __name__ == '__main__':
|
||||
isRunning = True
|
||||
firstCap = False
|
||||
firstLoop = True
|
||||
stat = "IDLE"
|
||||
bufferFull = 0
|
||||
variableMap = list()
|
||||
samples = dict()
|
||||
|
||||
try:
|
||||
fp = open("config.json")
|
||||
settings = json.load(fp)
|
||||
fp.close()
|
||||
except:
|
||||
print("Non posso aprire il file di configurazione!")
|
||||
|
||||
# Setup Logger
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.DEBUG)
|
||||
LOGGER.propagate = False
|
||||
FORMATTER = logging.Formatter((settings["logFormat"]), (settings["logTimeFormat"]))
|
||||
# File Logging
|
||||
fh = logging.FileHandler((settings["logFile"]))
|
||||
fh.setLevel(logging.WARNING)
|
||||
fh.setFormatter(FORMATTER)
|
||||
LOGGER.addHandler(fh)
|
||||
# Console Logging
|
||||
cl= logging.StreamHandler(sys.stdout)
|
||||
cl.setLevel(logging.INFO)
|
||||
cl.setFormatter(FORMATTER)
|
||||
LOGGER.addHandler(cl)
|
||||
|
||||
LOGGER.warning("NasoScope {} Started!".format(settings["version"]))
|
||||
|
||||
mqtt = client.Client(protocol=client.MQTTv31)
|
||||
mqtt.on_message = onMessage
|
||||
mqtt.on_connect = onConnect
|
||||
mqtt.on_disconnect = onDisconnect
|
||||
mqtt.connect(host=settings['mqttHost'], port=settings['mqttPort'])
|
||||
mqtt.subscribe(settings['mqttReceive'])
|
||||
mqtt.user_data_set(stat)
|
||||
mqtt.loop_start()
|
||||
|
||||
xmlReqTempl = xml.fromstring(templates.REQ_TEMPLATE)
|
||||
xmlRespTempl = xml.fromstring(templates.RESP_TEMPLATE)
|
||||
|
||||
while isRunning:
|
||||
if stat == "INI":
|
||||
r=getInfo()
|
||||
if r:
|
||||
LOGGER.info("Sto Monitorando-> HWid:{0}, rel:{1}"\
|
||||
.format(r["GetHWKey-R"]["HwKey"],r["GetHWKey-R"]["Release"]))
|
||||
stopSampling()
|
||||
closeChannel()
|
||||
r=openChannel()
|
||||
channelID = r["MonOpenChannel-R"]["ChannelID"]
|
||||
LOGGER.info("Apro il Canale-> {}"\
|
||||
.format(channelID))
|
||||
variableMap=setupOscope()
|
||||
LOGGER.info("Aggiungo le Variabili-> {}"\
|
||||
.format(variableMap))
|
||||
stat = "STARTCAP"
|
||||
else:
|
||||
LOGGER.error('Nessuna risposta dal CN')
|
||||
isRunning = False
|
||||
pass
|
||||
elif stat == "STARTCAP":
|
||||
r=startSampling()
|
||||
if r:
|
||||
LOGGER.info("Inizio la cattura-> t:{}ms"\
|
||||
.format(settings["samplePeriod"]))
|
||||
startTime = time.time()
|
||||
for k in settings["variables"]:
|
||||
samples[k["name"]] = {}
|
||||
for kk in k["codes"]:
|
||||
samples[k["name"]][kk] = []
|
||||
firstCap = True
|
||||
stat = "CAP"
|
||||
else:
|
||||
LOGGER.error("Impossibile Iniziare la Cattura")
|
||||
isRunning = False
|
||||
pass
|
||||
elif stat == "CAP":
|
||||
tempSamples = collectSamples(variableMap,channelID)
|
||||
if tempSamples is not False:
|
||||
if firstCap == True:
|
||||
firstTS = min([z[templates.SAM_TS] for x in tempSamples \
|
||||
for y in tempSamples[x] for z in tempSamples[x][y]])
|
||||
firstCap = False
|
||||
pass
|
||||
else:
|
||||
for ax in tempSamples:
|
||||
for reg in tempSamples[ax]:
|
||||
for idx,rec in enumerate(tempSamples[ax][reg]):
|
||||
tempSamples[ax][reg][idx]=((tempSamples[ax][reg][idx][templates.SAM_TS]-firstTS)/10**6,
|
||||
tempSamples[ax][reg][idx][templates.SAM_VAL])
|
||||
if tempSamples[ax][reg][idx][templates.SAM_TS] > settings["recordTime"]:
|
||||
samples[ax][reg] = samples[ax][reg][-(len(samples)-len(tempSamples)):]
|
||||
if bufferFull < 1:
|
||||
bufferFull = 1
|
||||
elif bufferFull == 1:
|
||||
LOGGER.warning("Buffer Campioni Pieno, inizio roll")
|
||||
bufferFull = 2
|
||||
else:
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
samples[ax][reg]+=tempSamples[ax][reg]
|
||||
pass
|
||||
pass
|
||||
pass
|
||||
if time.time() - startTime > settings["fileSaveTime"]:
|
||||
saveSamples(samples)
|
||||
startTime = time.time()
|
||||
LOGGER.info("{}".format(tempSamples))
|
||||
else:
|
||||
LOGGER.error("Disconnesso dal CN")
|
||||
stat = "STOP"
|
||||
pass
|
||||
elif stat == "STOP":
|
||||
stopSampling()
|
||||
closeChannel()
|
||||
saveSamples(samples)
|
||||
LOGGER.warning("Chiudo il Canale")
|
||||
stat = "IDLE"
|
||||
firstLoop = True
|
||||
pass
|
||||
elif stat == "IDLE" and firstLoop == True:
|
||||
LOGGER.info("Pronto a Iniziare Cattura")
|
||||
firstLoop = False
|
||||
else:
|
||||
pass
|
||||
time.sleep(settings["loopPeriod"])
|
||||
mqtt.disconnect()
|
||||
sys.exit(0)
|
||||
|
||||
117
NasoScope/templates.py
Normal file
117
NasoScope/templates.py
Normal file
@@ -0,0 +1,117 @@
|
||||
'''
|
||||
Created on 5 set 2019
|
||||
|
||||
@author: Emanuele Trabattoni
|
||||
'''
|
||||
VAR_NAME = 0
|
||||
VAR_REG = 1
|
||||
VAR_ID = 2
|
||||
|
||||
SAM_TS = 0
|
||||
SAM_VAL = 1
|
||||
|
||||
HTTP_HEADER = {
|
||||
'Content-Type':'text/xml',
|
||||
'Accept':'*/*',
|
||||
'Cache-Control':'no-cache'
|
||||
}
|
||||
|
||||
XML_HEADER = \
|
||||
'<?xml version="1.0" encoding="utf-8"?>\r\n'
|
||||
|
||||
REQ_TEMPLATE = \
|
||||
'<?xml version="1.0" encoding="utf-8"?> \
|
||||
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> \
|
||||
<soap:Body> \
|
||||
</soap:Body> \
|
||||
</soap:Envelope> '
|
||||
|
||||
RESP_TEMPLATE = \
|
||||
'<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:ns="urn:OPENcontrol"> \
|
||||
<SOAP-ENV:Body> \
|
||||
</SOAP-ENV:Body> \
|
||||
</SOAP-ENV:Envelope> \
|
||||
'
|
||||
XMLNS_ENV = {'xmlns:soap':'http://schemas.xmlsoap.org/soap/envelope/',
|
||||
'xmlns:xsi':'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xmlns:xsd':'http://www.w3.org/2001/XMLSchema'
|
||||
}
|
||||
|
||||
XMLNS_RESP = {'ns':'urn:OPENcontrol',
|
||||
'xsi':'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsd':'http://www.w3.org/2001/XMLSchema',
|
||||
'SOAP-ENV':'http://schemas.xmlsoap.org/soap/envelope/',
|
||||
'SOAP-ENC':'http://schemas.xmlsoap.org/soap/encoding/'
|
||||
}
|
||||
|
||||
XMLNS_BODY = {'xmlns':'urn:OPENcontrol'}
|
||||
|
||||
COMMANDS = {
|
||||
'GetHWKey': {
|
||||
'attrib': XMLNS_BODY
|
||||
},
|
||||
'GetAvailableCustomEvents': {
|
||||
'attrib': XMLNS_BODY ,
|
||||
'elem': {
|
||||
'MaxEvents': '64'
|
||||
}
|
||||
},
|
||||
'GetProcessConfNum': {
|
||||
'attrib': XMLNS_BODY
|
||||
},
|
||||
'GetAxesInfo3': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'AxisId':'65535',
|
||||
'AxesNum': '64'
|
||||
}
|
||||
},
|
||||
'GetSysTick': {
|
||||
'attrib': XMLNS_BODY
|
||||
},
|
||||
'MonOpenChannel': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'Synchronized': 'false'
|
||||
}
|
||||
},
|
||||
'MonCloseChannel': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'Synchronized': 'false'
|
||||
}
|
||||
},
|
||||
'MonAddVariable': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'ChannelID': '0',
|
||||
'VarDescr': {
|
||||
'Class':'1',
|
||||
'SubClass':'0',
|
||||
'DeviceID': 'XXXX',
|
||||
'Code':'XXXX',
|
||||
'Address':'0',
|
||||
'Signal':'0',
|
||||
'SamplingPeriod':'XXXX'}
|
||||
}
|
||||
},
|
||||
'MonStartSampling': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'ChannelID': '0'
|
||||
}
|
||||
},
|
||||
'MonStopSampling': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'ChannelID': '0'
|
||||
}
|
||||
},
|
||||
'MonGetVariableS': {
|
||||
'attrib': XMLNS_BODY,
|
||||
'elem': {
|
||||
'ChannelID': '0',
|
||||
'VariableID': 'XXXX',
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user