from __future__ import print_function import sys, time, os, socket import struct, binascii, re from datetime import datetime, timedelta from twisted.protocols.basic import LineReceiver from twisted.internet import reactor from twisted.python import usage, log from twisted.internet.serialport import SerialPort from twisted.web.server import Site from twisted.web.static import File try: # version > 0.8.0 from autobahn.wamp1.protocol import exportRpc except: from autobahn.wamp import exportRpc def timeToArray(timestring): # Converts time string of format 2013-12-12 23:12:23.122324 # to an array similiar to a datetime object try: splittedfull = timestring.split(' ') splittedday = splittedfull[0].split('-') splittedsec = splittedfull[1].split('.') splittedtime = splittedsec[0].split(':') datearray = splittedday + splittedtime datearray.append(splittedsec[1]) datearray = map(int,datearray) return datearray except: log.msg('Error while extracting time array') return [] def dataToFile(outputdir, sensorid, filedate, bindata, header): # File Operations try: hostname = socket.gethostname() path = os.path.join(outputdir,hostname,sensorid) # outputdir defined in main options class if not os.path.exists(path): os.makedirs(path) savefile = os.path.join(path, sensorid+'_'+filedate+".bin") if not os.path.isfile(savefile): with open(savefile, "wb") as myfile: myfile.write(header + "\n") myfile.write(bindata + "\n") else: with open(savefile, "a") as myfile: myfile.write(bindata + "\n") except: log.err("KERN - Protocol: Error while saving file") ## Environment protocol ## -------------------- class KernProtocol(LineReceiver): """ Protocol to read KERN balance data from RS232 The protocol defines the sensor name in its init section, which is used to dipatch url links and define local storage folders TODO: rounding error with datearray calculation - leads to microsecond diffs between timestamp and datearry ----- corrected that here c---- check out validity in other datasets (e.g. Lemi) """ ## need a reference to our WS-MCU gateway factory to dispatch PubSub events ## def __init__(self, wsMcuFactory, sensor, outputdir): self.wsMcuFactory = wsMcuFactory self.sensor = sensor self.hostname = socket.gethostname() self.outputdir = outputdir print(self.sensor) def connectionMade(self): log.msg('%s connected.' % self.sensor) def processKernData(self, data): """Convert raw ADC counts into SI units as per datasheets""" currenttime = datetime.utcnow() outdate = datetime.strftime(currenttime, "%Y-%m-%d") filename = outdate actualtime = datetime.strftime(currenttime, "%Y-%m-%dT%H:%M:%S.%f") outtime = datetime.strftime(currenttime, "%H:%M:%S") timestamp = datetime.strftime(currenttime, "%Y-%m-%d %H:%M:%S.%f") #header = "# MagPyBin, sensor_id, [parameterlist], [unit-conversion-list], packing string, length" packcode = '6hLL' sensorid = self.sensor header = "# MagPyBin %s %s %s %s %s %s %d" % (sensorid, '[var1]', '[Weight]', '[g]', '[10000]', packcode, struct.calcsize(packcode)) try: val1 = data[0].split(',') if len(val1) > 0: val = float(val1[1]) typ = val1[0] else: val = 0.0 typ = "NN" except: val = 0.0 typ = "NN" datearray = timeToArray(timestamp) try: datearray = timeToArray(timestamp) datearray.append(int(val*10000)) data_bin = struct.pack(packcode,*datearray) # File Operations dataToFile(self.outputdir, sensorid, filename, data_bin, header) except: log.msg('Error while packing binary data') pass try: # reformat time from datearray to acertain similar rounding of microsecs dob = datetime.datetime(*datearray[:7]) timestamp = datetime.strftime(dob,"%Y-%m-%d %H:%M:%S.%f") except: log.msg('Error reformating time - remove that !!!') pass evt0 = {'id': 0, 'value': self.hostname} evt1 = {'id': 1, 'value': timestamp} evt3 = {'id': 3, 'value': outtime} evt38 = {'id': 38, 'value': val} evt99 = {'id': 99, 'value': 'eol'} return evt0,evt1,evt3,evt38,evt99 def lineReceived(self, line): dispatch_url = "http://example.com/"+self.hostname+"/kern#"+self.sensor+"-value" try: data = line.split() if len(data) == 2: evt0,evt1,evt3,evt38,evt99 = self.processKernData(data) else: print('Data error') ## publish event to all clients subscribed to topic ## try: self.wsMcuFactory.dispatch(dispatch_url, evt0) except: log.err("Missing hostname") pass try: self.wsMcuFactory.dispatch(dispatch_url, evt1) except: pass try: self.wsMcuFactory.dispatch(dispatch_url, evt3) except: pass try: self.wsMcuFactory.dispatch(dispatch_url, evt38) self.wsMcuFactory.dispatch(dispatch_url, evt99) except: pass #log.msg("Analog value: %s" % str(evt4)) except ValueError: log.err('Unable to parse data %s' % line) #return