114 lines
3 KiB
Python
114 lines
3 KiB
Python
'''
|
|
Created on 05.12.2013
|
|
|
|
@author: Philipp Rauch
|
|
'''
|
|
from pymodbus.client.sync import ModbusTcpClient
|
|
from datetime import datetime
|
|
import time
|
|
from profile.datasheet import Datasheet
|
|
import struct
|
|
import numpy
|
|
|
|
_csv_lookup = { 'offset' : 'offset',
|
|
'type' : 'value - type',
|
|
'size' : 'size (Byte)',
|
|
'name' : 'Value name',
|
|
'time_offset' : 797}
|
|
|
|
def setup(conf):
|
|
'''
|
|
load message definition and connect to all pacs
|
|
'''
|
|
PACS = []
|
|
csv = '%s/%s' % (conf['config_dictionary'], conf['pac_csvfile'])
|
|
|
|
pac_csv = Datasheet()
|
|
pac_csv.loadDatasheet(strFile = csv)
|
|
messages = pac_csv.readDatasheet()
|
|
|
|
### INITIALIZE ###
|
|
PACS.append(messages)
|
|
if isinstance(conf['pac_ip'], list):
|
|
for ip in conf['pac_ip']:
|
|
PACS.append(ModbusTcpClient(ip))
|
|
else:
|
|
PACS.append(ModbusTcpClient(conf['pac_ip']))
|
|
|
|
### CONNECT ###
|
|
for PAC in PACS[1::]:
|
|
PAC.connect()
|
|
_set_time(PAC, _csv_lookup['time_offset'])
|
|
|
|
return PACS
|
|
|
|
def loop(PACS, item):
|
|
'''
|
|
get value of message and convert it to the right datatype
|
|
return the result
|
|
'''
|
|
|
|
row = PACS[0][PACS[0][_csv_lookup['offset']] == item[1]]
|
|
inx = row.index.values[0]
|
|
|
|
#print row.get('value - type')[inx]
|
|
valType = row.get(_csv_lookup['type'])[inx]
|
|
reg = row.get(_csv_lookup['size'])[inx]/2
|
|
|
|
type_picker = {'double' : _to_double,
|
|
'float' : _to_float,
|
|
'float + timestamp' : _to_float_time,
|
|
'long' : _to_long,
|
|
'timestamp' : _to_time_abs,
|
|
'Unsigned long' : _to_ulong,
|
|
'Unsigned short' : _to_ushort }
|
|
|
|
func = type_picker.get(valType, None)
|
|
if func is None:
|
|
raise NotImplementedError
|
|
|
|
res = PACS[item[0]].read_holding_registers(item[1], reg, unit=1)
|
|
return { row.get(_csv_lookup['name'])[inx] : func(res.registers) }
|
|
|
|
|
|
def _to_float_time(reg):
|
|
res = { 'value' : _to_float(reg[0:2]) }
|
|
res.update({ 'time' : _to_time_abs(reg[2:6]) })
|
|
return res
|
|
|
|
def _to_long(reg):
|
|
tmp = _to_ulong(reg)
|
|
s = struct.pack('=i', tmp)
|
|
return numpy.float32(struct.unpack('=l', s)[0])
|
|
|
|
def _to_double(reg):
|
|
tmp = int(reg[0]) << 3*16 | int(reg[1]) << 2*16 | int(reg[2]) << 16 | int(reg[3])
|
|
s = struct.pack('=q', tmp)
|
|
return numpy.float64(struct.unpack('=d', s)[0])
|
|
|
|
def _to_time_abs(reg):
|
|
timestamp = _to_ulong(reg)
|
|
date = datetime.fromtimestamp(timestamp)
|
|
return date
|
|
|
|
def _to_ulong(reg):
|
|
return numpy.int32(reg[0]) << 16 | int(reg[1])
|
|
|
|
def _to_ushort(reg):
|
|
return numpy.int16(reg[0])
|
|
|
|
def _to_float(reg):
|
|
tmp = _to_ulong(reg)
|
|
s = struct.pack('=i', tmp)
|
|
return numpy.float32(struct.unpack('=f', s)[0])
|
|
|
|
def _set_time(PAC, offset):
|
|
stamp = time.time()
|
|
high = int(int(stamp) >> 16)
|
|
low = int(int(stamp) & int(0xFFFF))
|
|
PAC.write_registers(offset, (high, low, 0, 0), unit=1)
|
|
|
|
def close(PACS):
|
|
### CLOSE ###
|
|
for PAC in PACS[1::]:
|
|
PAC.close()
|