Merge branch 'master' of git.rosstein.de:sf_lactor

This commit is contained in:
2018-09-25 20:04:40 +02:00
5 changed files with 264 additions and 60 deletions

25
DB.py
View File

@@ -122,6 +122,18 @@ class DB:
return cursor.fetchall ()
def getanimalnrbyrfid (self, rfid):
"""
Get Animalnr by RFID
"""
try:
cursor = self.executesql ("SELECT animalnr FROM animals WHERE rfid = '%s';" % rfid)
except:
print ("Couldnt read from animals")
return cursor.fetchone ()
def addmilkdata (self, data):
"""
Add Milkingdata
@@ -175,20 +187,23 @@ class DB:
if __name__ == "__main__":
conn = DB ('/opt/data/animaldb.sqlite', '/tmp/talog.sql', logtest, errlogtest)
anr = conn.getanimalnrbyrfid ('7678l43'.lstrip('0'))
if anr:
print (anr [0])
data = {'animalnr' : 711,
'earmark' : 'DE09 4711',
'rfid' : '123543546'
}
#conn.addanimal (data)
print (conn.getanimals ())
#print (conn.getanimals ())
data = {'animalnr' : 711,
'ts' : '2017.03.01 14:24:57',
'ammount' : '5.00',
'time' : '234'}
#conn.addmilkdata (data)
print (conn.getlastmilkdatabyanimal ('711', 3))
print ("All Milkingdata")
for ds in conn.getiallmilkdata ():
print (ds)
print (conn.getlastmilkdatabyanimal ('657', 3))
#print ("All Milkingdata")
#for ds in conn.getiallmilkdata ():
# print (ds)

122
Taurus.py
View File

@@ -1,4 +1,5 @@
from time import time, strftime
import codecs
from DB import *
entities = {}
@@ -19,6 +20,17 @@ entities ['201861'] = [
(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
@@ -36,9 +48,12 @@ entities ['201863'] = [
(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', 'N', 15, 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
@@ -59,7 +74,7 @@ Melkverbot
#NR, ART, ITEM, NAME, TYPE, LEN, RESOLUTION, UNIT, CODE
entities ['201867'] = [
(1, 'KEY', '00201896', 'Stallnummer', 'N', 6, 0, '', 0),
(2, 'OPT', '00900080', 'Ohrnummer', 'N', 15, 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)
]
@@ -71,14 +86,17 @@ 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', '00201830', 'Milchflussdauer', 'N', 3, 1, '', 0),
(7, 'MAN', '00900051', 'Milchflussdauer', 'N', 4, 1, '', 0),
(8, 'MAN', '00201860', 'Melkplatz', 'N',2, 0, '', 0)
]
@@ -108,13 +126,16 @@ class TAURUS:
def parsefile (self, path, filename):
"parse taurus file"
file = open (path + filename)
file = codecs.open (path + filename, 'r', 'cp1252')
currententity = 0
currentd = []
request = []
for line in file.readlines ():
if len (line) > 2:
self.log ("Line: %s" % line)
try:
self.log ("Line: %s" % line)
except:
self.log ("Line: couldn't be decoded")
linetype = line [0]
linestatus = line [1]
linedata = line [2:]
@@ -134,6 +155,7 @@ class TAURUS:
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
@@ -148,6 +170,7 @@ class TAURUS:
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'],
@@ -181,9 +204,23 @@ class TAURUS:
file.close ()
# Handle Requests
if request:
file = open (path + self.writefilename, 'w')
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')
@@ -249,7 +286,58 @@ class TAURUS:
return values
def createmilkdataset (self, animalinfo, ddef, nr):
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
"""
@@ -267,7 +355,7 @@ class TAURUS:
milkforbid = 1
retval = ''
mds = self.db.getlastmilkdatabyanimal (animalnr, nr)
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')
@@ -277,16 +365,19 @@ class TAURUS:
data ['00201729'] = mdate
data ['00202513'] = mtime
data ['00200488'] = float (ammount) / 1000.0
data ['00201830'] = float (time) / 60.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 + 1))
ds += data[item].rjust (int (length))
elif datatype == 'N':
_v = "%d" % (int (data[item] * (10**int (resolution))))
if item == '00202513':
_v = data [item]
else:
_v = "%d" % (int (data[item] * (10**int (resolution))))
ds += _v.rjust (int (length))
else:
ds += '?' * length
@@ -300,6 +391,13 @@ class TAURUS:
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')

View File

@@ -3,17 +3,17 @@ dbfile = /opt/data/animaldb.sqlite
candev = can0
[DEBUG]
loglevel = 6
loglevel = 9
debuglevel = 1
[HERDE]
herde = 1
herdepath = /srv/herde
herdereadfile = Tau_ms.2
herdewritefile = Tau_prc.2
herdereadfile = TAU_MS.2
herdewritefile = TAU_PRC.2
[Animal Recognition]
animalrecognition = 0
rfiddev = /dev/serial0
animalrecognition = 1
rfidip = 192.168.178.101
rfidport = 100

72
lactor.init Executable file
View File

@@ -0,0 +1,72 @@
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
#
# Function that starts the daemon/service
#
do_start()
{
pushd /opt/lactor
/opt/lactor/startlactor.sh &
popd
return 0
}
#
# Function that stops the daemon/service
#
do_stop()
{
pkill -f /opt/lactor/startlactor.sh
sleep 5s
pkill -KILL -f /opt/lactor/startlactor.sh
return 0
}
case "$1" in
start)
[ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME"
do_start
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
stop)
[ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME"
do_stop
case "$?" in
0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;;
2) [ "$VERBOSE" != no ] && log_end_msg 1 ;;
esac
;;
restart|force-reload)
#
# If the "reload" option is implemented then remove the
# 'force-reload' alias
#
log_daemon_msg "Restarting $DESC" "$NAME"
do_stop
case "$?" in
0|1)
do_start
case "$?" in
0) log_end_msg 0 ;;
1) log_end_msg 1 ;; # Old process is still running
*) log_end_msg 1 ;; # Failed to start
esac
;;
*)
# Failed to stop
log_end_msg 1
;;
esac
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 3
;;
esac
:

View File

@@ -2,12 +2,13 @@
import sys, os
from pathlib import Path
import can
import serial
from DB import *
from time import sleep, time, strftime
from datetime import *
from configparser import *
from Taurus import *
from socket import *
from select import select
bus = None
infotype = {0 : 'S-Buffer deleted',
@@ -19,6 +20,8 @@ infotype = {0 : 'S-Buffer deleted',
6 : 'state'
}
grfid = '0'
class CanListener (can.Listener):
def on_message_received (self, msg):
print ("Received Data")
@@ -32,6 +35,7 @@ class CanListener (can.Listener):
self.loglevel = 9
#[arbitration_id', 'data', 'dlc', 'id_type', 'is_error_frame', 'is_extended_id', 'is_remote_frame', 'timestamp']
#<class 'can.message.Message'>
#Timestamp: 1499861978.530813 ID: 0581 000 DLC: 8 20 20 20 20 30 30 30 30
@@ -102,8 +106,12 @@ class CanListener (can.Listener):
if infotype [_info_type] == 'animal nr':
if 'REQ' in str (_data):
self.log ("Anforderung Tiernummer von Tiererkennung", 3)
#FixMe AnimalNr from rFID
animalnr = 12
#AnimalNr from RFID
animalnr = 0
if int (grfid) > 0:
anr = self.db_con.getanimalnrbyrfid (grfid.lstrip('0'))
if anr:
animalnr = int (anr[0])
#_sendecho = 0
_repdata = bytearray (('REP00%03d' % animalnr).encode ())
self.waitack [_address] = 1
@@ -128,10 +136,13 @@ class CanListener (can.Listener):
#State requeset
elif infotype [_info_type] == 'state':
_sendecho = 0 #No Echo on State telegram
sdata = _data.decode("utf-8", "ignore")
if self.waitackst [_address]:
self.log ("Echo fuer Status erhalten", 3)
self.waitackst [_address] = 0
_sendecho = 0
elif ('MEL' in sdata) or ('GESP' in sdata) or ('UNBE' in sdata):
self.log ("unerwartetes Echo fuer Status erhalten", 3)
else:
animalnr = int (_data)
self.log ("Statusanfrage fuer Tiernummer %d" % animalnr)
@@ -160,7 +171,7 @@ class CanListener (can.Listener):
if len (_lastmilkdata):
_mdts, _mdanimalnr, _mdammount, _mdtime, _mplace = _lastmilkdata [0]
_mddt = datetime.strptime (_mdts, '%Y-%m-%d %H:%M:%S')
_lmdelta = (datetime.now() - _mddt).seconds
_lmdelta = int ((datetime.now() - _mddt).total_seconds())
self.log ("Letze Melkung war vor %s s" % _lmdelta, 5)
if (_lmdelta < 7200):
self.log ("2te Melkung", 1)
@@ -188,12 +199,12 @@ class CanListener (can.Listener):
elif infotype [_info_type] == 'milking time':
if self.dataset [_address]:
self.log ("Melkzeit fuer vorhandenen Datensatz im Puffer %s" % self.dataset [_address])
self.dataset [_address] ['time'] = int (_data)
self.dataset [_address] ['time'] = int (_data) / 100 * 60 + int (_data) % 100
animalinfo = self.db_con.getanimal (self.dataset [_address]['animalnr'])
if len (animalinfo):
self.log ("Tier in DB gefunden", 5)
else:
self.log ("Tier %d nicht in DB gefunden - wird autmatisch angelewgt" % (self.dataset [_address]['animalnr']), 1)
self.log ("Tier %d nicht in DB gefunden - wird autmatisch angelegt" % (self.dataset [_address]['animalnr']), 1)
#FixMe Check Animal Nr Range + x
_animaldata = {'animalnr' : self.dataset [_address]['animalnr'],
'earmark' : '2730000000000000',
@@ -209,7 +220,7 @@ class CanListener (can.Listener):
self.log ("Letzte Melkung war vor %s s" % _lmdelta, 5)
if _lmdelta < 7200:
self.log ("2te Melkung", 1)
self.log ("Addiere Mlichmenge Ald %d Neu %d, Zeit Alt %dNeu %d" % ( self.dataset [_address] ['ammount'], int (_mdammount), self.dataset [_address] ['time'],int (_mdtime)), 5)
self.log ("Addiere Mlichmenge Neu %d Alt %d, Zeit Neu %dAlt %d" % ( self.dataset [_address] ['ammount'], int (_mdammount), self.dataset [_address] ['time'],int (_mdtime)), 5)
self.dataset [_address] ['ts'] = _mdts
self.dataset [_address] ['ammount'] = self.dataset [_address] ['ammount'] + int (_mdammount)
self.dataset [_address] ['time'] = self.dataset [_address] ['time'] + int (_mdtime)
@@ -281,12 +292,12 @@ if __name__ == "__main__":
c_herdereadfile = config.get ('HERDE', 'herdereadfile')
if c_herde and not c_herdereadfile:
print ('No Readfile für HERDE Coupplingdefined')
print ('No Readfile for HERDE Coupplingdefined')
sys.exit (0)
c_herdewritefile = config.get ('HERDE', 'herdewritefile')
if c_herde and not c_herdewritefile:
print ('No Readfile für HERDE Coupplingdefined')
print ('No Readfile for HERDE Coupplingdefined')
sys.exit (0)
if c_herde:
taurus = TAURUS (dbcon, c_loglevel, c_herdewritefile)
@@ -294,27 +305,24 @@ if __name__ == "__main__":
c_animalrecognition = config.get ('Animal Recognition', 'animalrecognition')
if c_animalrecognition:
c_rfiddev = config.get ('Animal Recognition', 'rfiddev')
if not c_rfiddev:
print ('Animalrecognition configured')
c_rfidip = config.get ('Animal Recognition', 'rfidip')
c_rfidport = int (config.get ('Animal Recognition', 'rfidport'))
print (' with ip %s port %s' % (c_rfidip, c_rfidport))
if not c_rfidip or not c_rfidport:
print ('No RFID Device configured')
sys.exit (0)
"""
Nedap RFID Reader
Nedap RFID Reader over RS232 / TCP
"""
rfid = serial.Serial (port = c_rfiddev,\
baudrate = "9600",\
bytesize = 8,\
parity = "N",\
stopbits = 1,\
timeout = 0,\
xonxoff = 0,\
rtscts = 0,\
writeTimeout = None)
print ('RFID configured')
srfid = socket(AF_INET, SOCK_STREAM)
srfid.connect ((c_rfidip, c_rfidport))
herdefiletslatch = None
herdechanged = 0
readbuffer = ''
online = 0
animalnr = ''
rfidonline = 0
rfidnr = ''
while 1:
if c_herde:
if Path (c_herdepath + c_herdereadfile).exists ():
@@ -330,22 +338,33 @@ if __name__ == "__main__":
herdefiletslatch = _herdets
#Tiererkennung
if c_animalrecognition:
try:
d = rfid.read ()
if len (d):
readbuffer += d.decode("utf-8")
reads = [srfid]
writes = []
(read, writes, xlist) = select (reads, writes, [], 0.01)
for i in read:
data = i.recv (512)
if len (data):
d = data.decode("utf-8", "ignore")
readbuffer += d
if readbuffer [-2:] == '\r\n':
if online:
if rfidonline:
data = readbuffer.split (' ')
if len (data) == 3:
newanimalnr = data [2]
if newanimalnr != animalnr:
print ("Neue Tiernummer %s" % newanimalnr)
animalnr = newanimalnr
readbuffer = ''
online = 1
except KeyboardInterrupt:
newrfid = int (data [2]) % 100000000
if newrfid != rfidnr:
print ("Neue RFID %s" % newrfid)
rfidnr = newrfid
grfid = str (rfidnr)
readbuffer =''
rfidonline = 1
for i in xlist:
print ("Closed Socket")
i.close ()
bus.shutdown ()
rfid.close ()
sys.exit (0)
try:
foo = 0
except KeyboardInterrupt:
bus.shutdown ()
srfid.close ()