Files
sf_lactor/Taurus.py

404 lines
14 KiB
Python

from time import time, strftime
import codecs
from DB import *
entities = {}
"""
Entity 201861
Header
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201861'] = [
(1, 'KEY', '00000000', 'Typ', 'AN', 8, 0, '', 0),
(2, 'MAN', '00201575', 'Erstelldatum', 'N', 8, 0, 'CCYYMMDD', 0),
(3, 'MAN', '00201576', 'Erstellzeit', 'N', 6, 0, 'hhmmss', 0),
(2, 'MAN', '00201577', 'Systemstatus', 'N', 1, 0, '', 0),
(3, 'MAN', '00201681', 'Absender', 'AN', 24, 0, '', 0),
(4, 'MAN', '00201682', 'Empfaenger', 'AN', 24, 0, '', 0),
(7, 'MAN', '00502012', 'Software', 'AN', 10, 0, '', 0),
(8, 'MAN', '00201684', 'Senderversion', 'AN', 8, 0, '', 0),
(9, 'MAN', '00201685', 'ADED-Nation.-Vers.', 'AN', 8, 0, '', 0)
]
#CHHeaderDD type File date File time Sys status Sender Receiver System typeSoftw ver. DD version
#DH201861000000000800020157508000201576060002015770100020168124000201682240005020121000020168408000201685080
#VH201861DD 201705311140480DSP GmbH Aschara VC5 Herde++ 2.18STK 2.0
"""
Entity 201862
Zu-Abgang
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201862'] = []
"""
Entity 201863
Tierdaten
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201863'] = [
(1, 'KEY', '00201896', 'Stallnummer', 'N', 6, 0, '', 0),
(2, 'MAN', '00201812', 'Elektron. ID', 'AN', 15, 0, '', 0),
(3, 'MAN', '00200064', 'Gruppe', 'N', 2, 0, '', 0),
(4, 'MAN', '00201695', 'Geburtsdatum', 'N', 8, 0, 'CCYYMMDD', 0),
(5, 'MAN', '00200042', 'Kalbdatum', 'N', 8, 0, 'CCYYMMDD', 0),
(6, 'MAN', '00200060', 'Belegungsdatum', 'N', 8, 0, 'CCYYMMDD', 0),
(7, 'MAN', '00200513', 'Trockenstelldatum', 'N', 8, 0, 'CCYYMMDD', 0),
(8, 'MAN', '00201743', 'Datum Brunstkontrolle', 'N', 8, 0, 'CCYYMMDD', 0),
(9, 'MAN', '00900085', 'Tieruntersuchung', 'N', 1, 0, '', 0),
(10, 'MAN', '00900059', 'Datum Tieruntersuchung', 'N', 8, 0, 'CCYYMMDD', 0),
(11, 'MAN', '00900058', 'Laktationsnummer', 'N', 2, 0, '', 0),
(13, 'OPT', '00900080', 'Ohrnummer', 'AN', 15, 0, '', 0),
(14, 'OPT', '00200112', 'unbekannt', 'AN', 2, 0, '', 0),
(15, 'OPT', '00200050', 'unbekannt', 'AN', 8, 0, '', 0),
(16, 'OPT', '00201592', 'unbekannt', 'AN', 6, 0, '', 0)
]
#Fixme Ohrnummer numerisch
"""
Entity 201865
Futterdaten
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201865'] = [
(1, 'KEY', '00201896', 'Stallnummer', 'N', 6, 0, '', 0),
(2, 'MAN', '00201859', 'Futter Nr 1/2', 'N', 1, 0, '', 0),
(3, 'MAN', '00201828', 'Futter Soll', 'N', 6, 3, '', 0),
(4, 'MAN', '00201831', 'Futter Rest', 'N', 6, 3, '', 0),
(5, 'MAN', '00201856', 'Futter Gesamt', 'N', 8, 3, '', 0)
]
"""
Entity 201867
Melkverbot
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201867'] = [
(1, 'KEY', '00201896', 'Stallnummer', 'N', 6, 0, '', 0),
(2, 'OPT', '00900080', 'Ohrnummer', 'AN', 15, 0, '', 0),
(3, 'MAN', '00004401', 'Start Melkverbot', 'N', 8, 0, 'CCYYMMDD', 0),
(4, 'MAN', '00004402', 'Ende Melkverbot', 'N', 8, 0, 'CCYYMMDD', 0)
]
"""
Entity 201866
Gemelkerfassung
"""
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
#RN2018660020189606000900080150002017290800020251306000821005050002004880310020159206100201596031002004890310090005104200201860020
#RN20186600201896060009000801500020172908000202513060 002004880310020159206100201596031002004890310020183003100201860020
entities ['201866'] = [
(1, 'KEY', '00201896', 'Stallnummer', 'N', 6, 0, '', 0),
(2, 'MAN', '00201729', 'Melkdatum', 'N', 8, 0, 'CCYYMMDD', 0),
(3, 'MAN', '00202513', 'Melkzeit', 'N', 6, 0, 'hhmmss', 0),
(4, 'MAN', '00821005', 'Melkdauer', 'N', 5, 0, '', 0),
(4, 'MAN', '00200488', 'Milch', 'N', 3, 1, '', 0),
(5, 'MAN', '00201596', 'Durchschn. Melkgeschwindigkeit', 'N', 3, 2, '', 0),
(6, 'OPT', '00200489', 'Temperatur', 'N', 3, 1, '', 0),
(7, 'MAN', '00900051', 'Milchflussdauer', 'N', 4, 1, '', 0),
(8, 'MAN', '00201860', 'Melkplatz', 'N',2, 0, '', 0)
]
class TAURUS:
def __init__ (self, db, loglevel, writefilename):
self.db = db
self.loglevel = loglevel
#Optional Fields for an entity
self.entityfields = {'880022': ['800702', '900070']}
self.writefilename = writefilename
def log (self, msg, _level = 3):
"""
Logfile
Loglevel 9 = print to console
"""
if self.loglevel == 9:
print (msg)
if _level <= self.loglevel:
file = open ("/var/log/lactor/" + os.getcwd().split('/')[-1] + '.err', "a")
dt = datetime.now ()
file.write ("%4d-%02d-%02d %02d:%02d:%02d.%06d: " %(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond) + msg + "\n")
file.close ()
def parsefile (self, path, filename):
"parse taurus file"
file = codecs.open (path + filename, 'r', 'cp1252')
currententity = 0
currentd = []
request = []
for line in file.readlines ():
if len (line) > 2:
try:
self.log ("Line: %s" % line)
except:
self.log ("Line: couldn't be decoded")
linetype = line [0]
linestatus = line [1]
linedata = line [2:]
if linetype == 'D':
#Definition
if linestatus == 'H':
self.log ("Definition Header", 9)
currententity, currentd = self.parsed (linedata)
elif linestatus == 'N':
self.log ("Definition Normaldaten", 9)
currententity, currentd = self.parsed (linedata)
elif linetype == 'R':
#Request
if linestatus == 'N':
self.log ("Request Normaldaten", 9)
reqentity, reqd = self.parsed (linedata)
self.log ("Request Normaldaten entity %s" % reqentity, 9)
self.log ("Request Normaldaten daten %s" % reqd, 9)
request.append ((reqentity, reqd))
elif linetype == 'V':
#Values
entity = linedata [:6]
linevalues = linedata [6:]
if currententity == entity:
values = self.parsev (currentd, linevalues)
self.log (repr (values), 9)
if linestatus == 'H':
self.log ("Header Daten", 9)
elif linestatus == 'N':
self.log ("Normaldaten", 9)
if currententity == '201863':
self.log ("Tierdaten updaten", 6)
self.log ("Ohrmakre '%s'" % values ['00900080'], 6)
animaldata = {'animalnr' : values ['00201896'],
'earmark' : values ['00900080'],
'rfid' : values ['00201812'],
'forbidmilk' : 0}
self.db.addanimal (animaldata)
elif currententity == '201867':
self.log ("Melkverbot updaten", 6)
forbiddata = {'animalnr' : values ['00201896'],
'tsforbidstart' : '',
'tsforbidend' :''}
try:
tsstart = datetime.strptime (str (values ['00004401']), '%Y%m%d')
forbiddata ['tsforbidstart'] = tsstart
except:
self.log ("Wertfehler Melkverbot Startzeitstempel : %s"% values ['00004401'])
try:
tsend = datetime.strptime (str (values ['00004402']) + '235959', '%Y%m%d%H%M%S')
forbiddata ['tsforbidend'] = tsend
except:
self.log ("Wertfehler Melkverbot Endzeitstempel : %s"% values ['00004402'])
self.db.updatemilkingforbid (forbiddata)
elif linetype == 'E':
#End of Logical File
self.log ("Ende Logisches File")
elif linetype == 'Z':
#End of Physical File
break
file.close ()
# Handle Requests
if request:
self.log ("Path %s" % path)
file = codecs.open (path + self.writefilename, 'w', 'cp1252')
#Header
wline = self.generated ('201861', entities ['201861'])
file.write (wline + '\n')
wline = self.createaheader (entities ['201861'])
file.write (wline + '\n')
for reqentity, reqd in request:
self.log ("Request %s ausfuehren" % reqentity)
if reqentity == '201863':
wline = self.generated (reqentity, reqd)
file.write (wline + '\n')
for animalinfo in self.db.getanimals ():
wline = self.createanimaldataset (animalinfo, reqd)
if wline:
file.write (wline + '\n')
if reqentity == '201865':
wline = self.generated (reqentity, reqd)
file.write (wline + '\n')
if reqentity == '201866':
wline = self.generated (reqentity, reqd)
file.write (wline + '\n')
for animalinfo in self.db.getanimals ():
wline = self.createmilkdataset (animalinfo, reqd, 10)
if wline:
file.write (wline + '\n')
file.write (wline + 'EN\n')
file.write (wline + 'ZN\n')
file.close ()
def generated (self, entity, ddef):
#Generate Datadefiniton
l = 'DN' + entity
for nr, art, item, name, datatype, length, resolution, unit, code in ddef:
l += '%s%02d%01d' % (item, length, resolution)
return l
def parsed (self, data):
"parse an Dx and return datasetdefinition"
entityid = data [:6]
_data = data [6:].replace ('\n', '').replace ('\r', '')
entity = entities [entityid]
self.log ("Defdata length: %d" % len(_data))
ds = []
for i in range (0, len (_data) , 11):
_item = _data [i: i + 8]
_len = int (_data [i + 8: i + 10])
_unit = _data [i + 10:]
self.log ("Itemid %s" % _item, 9)
for nr, art, item, name, datatype, length, resolution, unit, code in entity:
if _item == item:
ds.append ((nr, art, item, name, datatype, length, resolution, unit, code))
if _len != length:
self.log ("Error Size was %d instead of %d" % (_len, length), 1)
return entityid,ds
def parsev (self, definition, data):
"""
parse value
"""
_data = data
values = {}
for nr, art, item, name, datatype, length, resolution, unit, code in definition:
_value = _data[:length]
if datatype == 'N':
try:
_value = int (_value)
except:
if '?' in _value:
_value = 0
else:
self.log ("Wertfehler %s" % _value)
values [item] = _value
_data = _data[length:]
return values
def createanimaldataset (self, animalinfo, ddef):
"""
Tierdatensatz
"""
animalnr, earmark, rfid, tsforbidstart, tsforbidend = animalinfo
data = {'00201896': animalnr}
data ['00900080'] = earmark
data ['00201812'] = rfid
ds = "VN201863"
for nr, art, item, name, datatype, length, resolution, unit, code in ddef:
if item in data:
if datatype == 'AN':
ds += str (data[item]).rjust (int (length))
elif datatype == 'N':
_v = "%d" % (int (data[item] * (10**int (resolution))))
ds += _v.rjust (int (length))
else:
ds += '?' * length
self.log (ds, 9)
return ds
def createaheader (self, ddef):
"""
Header
"""
data = {'00000000': 'DD'}
data ['00201575'] = datetime.now().strftime ('%Y%m%d')
data ['00201576'] = datetime.now().strftime ('%H%M%S')
data ['00201577'] = 0
data ['00201681'] = 'Siliconform'
data ['00201682'] = 'Herde++'
data ['00502012'] = 'pyLactor'
data ['00201684'] = '1.00'
data ['00201685'] = 'TK 2.0'
ds = "VN201861"
for nr, art, item, name, datatype, length, resolution, unit, code in ddef:
if item in data:
if datatype == 'AN':
ds += str (data[item]).rjust (int (length))
elif datatype == 'N':
_v = "%d" % (int (data[item] * (10**int (resolution))))
ds += _v.rjust (int (length))
else:
ds += '?' * length
self.log (ds, 9)
return ds
def createmilkdataset (self, animalinfo, ddef, milkings):
"""
Creating entity for 880022
"""
animalnr, earmark, rfid, tsforbidstart, tsforbidend = animalinfo
#Check milking forbidden
milkforbid = 0
if tsforbidstart:
dttsforbidstart = datetime.strptime (tsforbidstart, '%Y-%m-%d %H:%M:%S')
if datetime.now () > dttsforbidstart:
if tsforbidend:
dttsforbidend = datetime.strptime (tsforbidend, '%Y-%m-%d %H:%M:%S')
if datetime.now () <= dttsforbidend:
milkforbid = 1
else:
milkforbid = 1
retval = ''
mds = self.db.getlastmilkdatabyanimal (animalnr, milkings)
for md in mds:
ts, animalnr, ammount, time, milkplace = md
dt = datetime.strptime (ts, '%Y-%m-%d %H:%M:%S')
mdate = dt.strftime ('%Y%m%d')
mtime = dt.strftime ('%H%M%S')
data = {'00201896': animalnr}
data ['00201729'] = mdate
data ['00202513'] = mtime
data ['00200488'] = float (ammount) / 1000.0
data ['00821005'] = int (time)
data ['00201860'] = milkplace
ds = "VN201866"
for nr, art, item, name, datatype, length, resolution, unit, code in ddef:
if item in data:
if datatype == 'AN':
ds += data[item].rjust (int (length))
elif datatype == 'N':
if item == '00202513':
_v = data [item]
else:
_v = "%d" % (int (data[item] * (10**int (resolution))))
ds += _v.rjust (int (length))
else:
ds += '?' * length
if retval:
retval += '\n'
retval += ds
self.log (ds, 9)
return retval
if __name__ == "__main__":
taurus = TAURUS (DB ('/opt/data/animaldb.sqlite', '/tmp/talog.sql', logtest, errlogtest), loglevel = 9, writefilename = 'rep.taur')
print ("Orginal")
taurus.parsefile ('sampledata/', 'Tau_ms.2')
print ("UPDATE")
taurus.parsefile ('sampledata/', 'Update.taur')
print ("REQUEST")
taurus.parsefile ('sampledata/', 'TAU_REQ_20180116.2')
print ("MELKverbot")
taurus.parsefile ('sampledata/', 'Melkverbot.taur')
print ("REQUEST")
taurus.parsefile ('sampledata/', 'Request.taur')