404 lines
14 KiB
Python
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')
|