''' 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()