Backup
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
*~
|
||||
*.pyc
|
||||
*.AppleDouble/
|
||||
lactor.cfg
|
||||
.DS_Store
|
||||
sampledata
|
||||
|
||||
24
DB.py
24
DB.py
@@ -80,7 +80,7 @@ class DB:
|
||||
Return all Data of animals
|
||||
"""
|
||||
try:
|
||||
cursor = self.executesql ("SELECT animalnr, earmark, rfid, forbidmilk FROM animals;")
|
||||
cursor = self.executesql ("SELECT animalnr, earmark, rfid, tsforbidstart, tsforbidend FROM animals;")
|
||||
except:
|
||||
return None
|
||||
|
||||
@@ -93,18 +93,29 @@ class DB:
|
||||
Add animal
|
||||
"""
|
||||
try:
|
||||
cursor = self.executesql ("INSERT OR REPLACE INTO animals (animalnr, earmark, rfid, forbidmilk ) VALUES ('%(animalnr)d', '%(earmark)s', '%(rfid)s', '%(forbidmilk)s');" % data)
|
||||
cursor = self.executesql ("INSERT OR REPLACE INTO animals (animalnr, earmark, rfid) VALUES ('%(animalnr)d', '%(earmark)s', '%(rfid)s');" % data)
|
||||
except:
|
||||
print ("Couldnt insert into animals")
|
||||
raise Warning
|
||||
|
||||
|
||||
def updatemilkingforbid (self, data):
|
||||
"""
|
||||
Update Milking Forbid
|
||||
"""
|
||||
try:
|
||||
cursor = self.executesql ("UPDATE animals set tsforbidstart = '%(tsforbidstart)s', tsforbidend = '%(tsforbidend)s' WHERE animalnr = '%(animalnr)d';" % data)
|
||||
except:
|
||||
print ("Couldnt update milkforbid information")
|
||||
raise Warning
|
||||
|
||||
|
||||
def getanimal (self, animalnr):
|
||||
"""
|
||||
Get Animaldata
|
||||
"""
|
||||
try:
|
||||
cursor = self.executesql ("SELECT animalnr, earmark, rfid, forbidmilk FROM animals WHERE animalnr = '%s';" % animalnr)
|
||||
cursor = self.executesql ("SELECT animalnr, earmark, rfid, tsforbidstart, tsforbidend FROM animals WHERE animalnr = '%s';" % animalnr)
|
||||
except:
|
||||
print ("Couldnt read from animals")
|
||||
|
||||
@@ -127,7 +138,6 @@ class DB:
|
||||
Add Milkingdata
|
||||
"""
|
||||
try:
|
||||
print ("UPDATE milkdata SET ammount = '%(ammount)s', time = '%(time)s' WHERE ts='%(ts)s' AND animalnr = '%(animalnr)d';" % data)
|
||||
cursor = self.executesql ("UPDATE milkdata SET ammount = '%(ammount)s', time = '%(time)s' WHERE ts='%(ts)s' AND animalnr = '%(animalnr)d';" % data)
|
||||
except:
|
||||
print ("Couldnt update milkdata")
|
||||
@@ -152,7 +162,7 @@ class DB:
|
||||
Return Milkingdata of Animal
|
||||
"""
|
||||
try:
|
||||
cursor = self.executesql ("SELECT ts, animalnr, ammount, time FROM milkdata WHERE animalnr = '%d' ORDER BY ts DESC LIMIT %d;" % (int (animalnr), last))
|
||||
cursor = self.executesql ("SELECT ts, animalnr, ammount, time, milkplace FROM milkdata WHERE animalnr = '%d' ORDER BY ts DESC LIMIT %d;" % (int (animalnr), last))
|
||||
except:
|
||||
return None
|
||||
|
||||
@@ -167,8 +177,8 @@ if __name__ == "__main__":
|
||||
conn = DB ('/opt/data/animaldb.sqlite', '/tmp/talog.sql', logtest, errlogtest)
|
||||
data = {'animalnr' : 711,
|
||||
'earmark' : 'DE09 4711',
|
||||
'rfid' : '123543546',
|
||||
'forbidmilk': '0'}
|
||||
'rfid' : '123543546'
|
||||
}
|
||||
#conn.addanimal (data)
|
||||
print (conn.getanimals ())
|
||||
|
||||
|
||||
305
Taurus.py
Normal file
305
Taurus.py
Normal file
@@ -0,0 +1,305 @@
|
||||
from time import time, strftime
|
||||
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)
|
||||
]
|
||||
|
||||
"""
|
||||
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', 'N', 15, 0, '', 0)
|
||||
]
|
||||
|
||||
"""
|
||||
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', 'N', 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
|
||||
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', '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),
|
||||
(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 = open (path + filename)
|
||||
currententity = 0
|
||||
currentd = []
|
||||
request = []
|
||||
for line in file.readlines ():
|
||||
if len (line) > 2:
|
||||
self.log ("Line: %s" % line)
|
||||
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)
|
||||
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)
|
||||
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:
|
||||
file = open (path + self.writefilename, 'w')
|
||||
for reqentity, reqd in request:
|
||||
self.log ("Request %s ausfuehren" % reqentity)
|
||||
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 createmilkdataset (self, animalinfo, ddef, nr):
|
||||
"""
|
||||
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, nr)
|
||||
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 ['00201830'] = float (time) / 60.0
|
||||
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))
|
||||
elif datatype == 'N':
|
||||
_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')
|
||||
taurus.parsefile ('sampledata/', 'Update.taur')
|
||||
taurus.parsefile ('sampledata/', 'Melkverbot.taur')
|
||||
taurus.parsefile ('sampledata/', 'Request.taur')
|
||||
@@ -2,12 +2,15 @@ CREATE TABLE animals (
|
||||
animalnr INTEGER UNIQUE NOT NULL,
|
||||
earmark CHAR (25) NOT NULL,
|
||||
rfid INTEGER,
|
||||
forbidmilk CHAR (1) default '0'
|
||||
forbidmilk CHAR (1) default '0',
|
||||
tsforbidstart timestamp (14),
|
||||
tsforbidend timestamp (14)
|
||||
);
|
||||
|
||||
CREATE TABLE milkdata (
|
||||
ts timestamp (14) NOT NULL,
|
||||
animalnr INTEGER NOT NULL,
|
||||
ammount decimal(10,2) NOT NULL default '0',
|
||||
time integer NOT NULL
|
||||
time integer NOT NULL,
|
||||
milkplace INTEGER NOT NULL default 1
|
||||
);
|
||||
|
||||
19
lactor.cfg.tpl
Normal file
19
lactor.cfg.tpl
Normal file
@@ -0,0 +1,19 @@
|
||||
[Settings]
|
||||
dbfile = /opt/data/animaldb.sqlite
|
||||
candev = can0
|
||||
|
||||
[DEBUG]
|
||||
loglevel = 6
|
||||
debuglevel = 1
|
||||
|
||||
[HERDE]
|
||||
herde = 1
|
||||
herdepath = /srv/herde
|
||||
herdereadfile = Tau_ms.2
|
||||
herdewritefile = Tau_prc.2
|
||||
|
||||
|
||||
[Animal Recognition]
|
||||
animalrecognition = 0
|
||||
rfiddev = /dev/serial0
|
||||
|
||||
206
lactor.py
206
lactor.py
@@ -1,7 +1,13 @@
|
||||
#!/usr/bin/env python3
|
||||
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 *
|
||||
|
||||
bus = None
|
||||
infotype = {0 : 'S-Buffer deleted',
|
||||
@@ -18,8 +24,8 @@ class CanListener (can.Listener):
|
||||
print ("Received Data")
|
||||
self.CanDecode (msg)
|
||||
|
||||
def set_db (self, dbpath = '/opt/lactor/animaldb.sqlite'):
|
||||
self.db_con = DB (dbpath, '/tmp/talog.sql', logtest, errlogtest)
|
||||
def set_db (self, dbcon):
|
||||
self.db_con = dbcon
|
||||
self.dataset = [None] * 128
|
||||
self.waitack = [0] * 128
|
||||
self.waitackst = [0] * 128
|
||||
@@ -49,41 +55,41 @@ class CanListener (can.Listener):
|
||||
Decoding Can Telegram
|
||||
"""
|
||||
if msg.is_extended_id:
|
||||
self.log ("Rcvd Msg with Extended ID", 0)
|
||||
self.log ("Msg Mit Erweiterter ID erhalten", 0)
|
||||
return
|
||||
if msg.is_error_frame:
|
||||
self.log ("Rcvd Msg Error Frame", 0)
|
||||
self.log ("Msg Error Frame erhalten", 0)
|
||||
return
|
||||
if msg.is_remote_frame:
|
||||
self.log ("Rcvd Msg Remote Frame", 0)
|
||||
self.log ("Msg Remote Frame erhalten", 0)
|
||||
return
|
||||
|
||||
_id = msg.arbitration_id
|
||||
self.log ("Msg %s" % msg, 9)
|
||||
self.log ("Msg: %s" % msg, 9)
|
||||
#Pos 11 Direction
|
||||
if not is_set (_id, 10):
|
||||
self.log ("Received Data to xLactor", 0)
|
||||
self.log ("Daten fur xLactor Steuerung erhalten", 0)
|
||||
return
|
||||
|
||||
#Pos 8-10 Infotype
|
||||
_info_type = (_id & 0b01110000000) >> 7
|
||||
self.log ("Infotype: %s %s" % (hex (_id), infotype [_info_type]), 3)
|
||||
self.log ("Infotyp: %s %s" % (hex (_id), infotype [_info_type]), 3)
|
||||
|
||||
#Pos 1-7 Address
|
||||
_address = (_id & 0b00001111111)
|
||||
self.log ("Address: %d" % _address, 4)
|
||||
self.log ("Addresse: %d" % _address, 4)
|
||||
#Determine Addresstype
|
||||
if ((_address & 0b1000000) == 0b0000000):
|
||||
self.log ("Terminal %d" % _address, 3)
|
||||
elif ((_address & 0b1110000) == 0b1000000):
|
||||
#Obsolete
|
||||
self.log ("Gatecontrol %d" % _address, 3)
|
||||
self.log ("Tuersteuerung obsolete %d" % _address, 3)
|
||||
elif ((_address & 0b1110000) == 0b1010000):
|
||||
#Obsolete
|
||||
self.log ("Animalrecognition %d" % _address, 3)
|
||||
self.log ("Tiererkennung obsolete %d" % _address, 3)
|
||||
elif ((_address & 0b1110000) == 0b1100000):
|
||||
#Obsolete
|
||||
self.log ("WateringPlace %d" & _address, 3)
|
||||
self.log ("Wasserplatz obsolete %d" & _address, 3)
|
||||
elif ((_address & 0b1110000) == 0b1110000):
|
||||
#Obsolete
|
||||
self.log ("Other %d" % _address, 1)
|
||||
@@ -95,7 +101,7 @@ class CanListener (can.Listener):
|
||||
#Animalnr request
|
||||
if infotype [_info_type] == 'animal nr':
|
||||
if 'REQ' in str (_data):
|
||||
self.log ("Requested AnimalNr from Recognition", 3)
|
||||
self.log ("Anforderung Tiernummer von Tiererkennung", 3)
|
||||
#FixMe AnimalNr from rFID
|
||||
animalnr = 12
|
||||
#_sendecho = 0
|
||||
@@ -103,63 +109,74 @@ class CanListener (can.Listener):
|
||||
self.waitack [_address] = 1
|
||||
|
||||
elif self.waitack [_address]:
|
||||
self.log ("Received Echo", 3)
|
||||
self.log ("Echo erhalten", 3)
|
||||
self.waitack [_address] = 0
|
||||
_sendecho = 0
|
||||
else:
|
||||
self.log ("New Milking Data", 3)
|
||||
self.log ("Neue Melkdaten erhalten", 3)
|
||||
_animalnr = int (_data)
|
||||
if _animalnr:
|
||||
if self.dataset [_address]:
|
||||
self.log ("A Milkingdataset already esists %s" % self.dataset [_address])
|
||||
self.log ("Es existiert bereits ein Melkdatensatz %s" % self.dataset [_address])
|
||||
self.dataset [_address] = {'animalnr' : _animalnr,
|
||||
'ts' : strftime ("%Y-%m-%d %H:%M:%S"),
|
||||
'ammount' : 0}
|
||||
else:
|
||||
self.dataset [_address] = None
|
||||
self.log ("AnimalNr is 0 ignore Milkingdata")
|
||||
self.log ("Tiernummer ist 0 ignoriere Melkdaten")
|
||||
|
||||
#State requeset
|
||||
elif infotype [_info_type] == 'state':
|
||||
_sendecho = 0 #No Echo on State telegram
|
||||
if self.waitackst [_address]:
|
||||
self.log ("Received Echo for Status", 3)
|
||||
self.log ("Echo fuer Status erhalten", 3)
|
||||
self.waitackst [_address] = 0
|
||||
_sendecho = 0
|
||||
else:
|
||||
animalnr = int (_data)
|
||||
self.log ("Statusrequest for animal %d" % animalnr)
|
||||
self.log ("Statusanfrage fuer Tiernummer %d" % animalnr)
|
||||
animalinfo = self.db_con.getanimal (animalnr)
|
||||
_ammountestimated = 12
|
||||
if len (animalinfo):
|
||||
_aianimalnr, _aiearmark, _airfid, _aiforbidmilk = animalinfo[0]
|
||||
if _aiforbidmilk != '0':
|
||||
self.log ("Milking is forbidden %s" % _aiforbidmilk, 1)
|
||||
_aianimalnr, _aiearmark, _airfid, _aitsforbidstart, _aitsforbidend = animalinfo[0]
|
||||
_milkforbid = 0
|
||||
if _aitsforbidstart:
|
||||
dttsforbidstart = datetime.strptime (_aitsforbidstart, '%Y-%m-%d %H:%M:%S')
|
||||
if datetime.now () > dttsforbidstart:
|
||||
if _aitsforbidend:
|
||||
dttsforbidend = datetime.strptime (_aitsforbidend, '%Y-%m-%d %H:%M:%S')
|
||||
if datetime.now () <= dttsforbidend:
|
||||
_milkforbid = 1
|
||||
else:
|
||||
_milkforbid = 1
|
||||
|
||||
if _milkforbid:
|
||||
self.log ("Melksperre ist gesetzt" , 1)
|
||||
_repdata = bytearray ('GESP '.encode ())
|
||||
self.waitackst [_address] = 1
|
||||
else:
|
||||
self.log ("Animal is Ok check milking data", 1)
|
||||
self.log ("Tier ist Ok checke Melkdaten", 1)
|
||||
_lastmilkdata = self.db_con.getlastmilkdatabyanimal (animalnr, 1)
|
||||
if len (_lastmilkdata):
|
||||
_mdts, _mdanimalnr, _mdammount, _mdtime = _lastmilkdata [0]
|
||||
_mdts, _mdanimalnr, _mdammount, _mdtime, _mplace = _lastmilkdata [0]
|
||||
_mddt = datetime.strptime (_mdts, '%Y-%m-%d %H:%M:%S')
|
||||
_lmdelta = (datetime.now() - _mddt).seconds
|
||||
self.log ("Delta to Last Milking was %s s" % _lmdelta, 5)
|
||||
self.log ("Letze Melkung war vor %s s" % _lmdelta, 5)
|
||||
if (_lmdelta < 7200):
|
||||
self.log ("2nd Milking", 1)
|
||||
self.log ("2te Melkung", 1)
|
||||
_repdata = bytearray ('2MEL '.encode ())
|
||||
self.waitackst [_address] = 1
|
||||
else:
|
||||
self.log ("All Ok", 5)
|
||||
self.log ("Alles Ok", 5)
|
||||
_repdata = bytearray ((' OK%04d' % int (_ammountestimated)).encode ())
|
||||
self.waitackst [_address] = 1
|
||||
else:
|
||||
self.log ("All Ok", 5)
|
||||
self.log ("Alles Ok", 5)
|
||||
_repdata = bytearray ((' OK%04d' % int (_ammountestimated)).encode ())
|
||||
self.waitackst [_address] = 1
|
||||
|
||||
else:
|
||||
self.log ("Animal not in DB", 1)
|
||||
self.log ("Tier nicht in DB", 1)
|
||||
_repdata = bytearray ('UNBE '.encode ())
|
||||
self.waitackst [_address] = 1
|
||||
|
||||
@@ -167,46 +184,45 @@ class CanListener (can.Listener):
|
||||
if self.dataset [_address]:
|
||||
self.dataset [_address] ['ammount'] = int (_data)
|
||||
else:
|
||||
self.log ("Dataset empty ignoring Milking ammount", 1)
|
||||
self.log ("Datensatzpuffer leer ignore Milchmenge", 1)
|
||||
elif infotype [_info_type] == 'milking time':
|
||||
if self.dataset [_address]:
|
||||
self.log ("Milking Time for existing Dataset %s" % self.dataset [_address])
|
||||
self.log ("Melkzeit fuer vorhandenen Datensatz im Puffer %s" % self.dataset [_address])
|
||||
self.dataset [_address] ['time'] = int (_data)
|
||||
animalinfo = self.db_con.getanimal (self.dataset [_address]['animalnr'])
|
||||
if len (animalinfo):
|
||||
self.log ("Found animal in DB", 5)
|
||||
self.log ("Tier in DB gefunden", 5)
|
||||
else:
|
||||
self.log ("Animal %d not found in animaldb create" % (self.dataset [_address]['animalnr']), 1)
|
||||
self.log ("Tier %d nicht in DB gefunden - wird autmatisch angelewgt" % (self.dataset [_address]['animalnr']), 1)
|
||||
#FixMe Check Animal Nr Range + x
|
||||
_animaldata = {'animalnr' : self.dataset [_address]['animalnr'],
|
||||
'earmark' : '2730000000000000',
|
||||
'rfid' : '',
|
||||
'forbidmilk' : '0'}
|
||||
'rfid' : ''}
|
||||
self.db_con.addanimal (_animaldata)
|
||||
|
||||
self.log ("Check last milking data", 1)
|
||||
self.log ("Letzte Melkdaten pruefen", 1)
|
||||
_lastmilkdata = self.db_con.getlastmilkdatabyanimal (self.dataset [_address]['animalnr'], 1)
|
||||
if len (_lastmilkdata):
|
||||
_mdts, _mdanimalnr, _mdammount, _mdtime = _lastmilkdata [0]
|
||||
_mdts, _mdanimalnr, _mdammount, _mdtime, _mplace = _lastmilkdata [0]
|
||||
_mddt = datetime.strptime (_mdts, '%Y-%m-%d %H:%M:%S')
|
||||
_lmdelta = (datetime.now() - _mddt).seconds
|
||||
self.log ("Delta to Last Milking was %s s" % _lmdelta, 5)
|
||||
self.log ("Letzte Melkung war vor %s s" % _lmdelta, 5)
|
||||
if _lmdelta < 7200:
|
||||
self.log ("2nd Milking", 1)
|
||||
self.log ("Adding Ammount Old %d New %d, Time Old %d New %d" % ( self.dataset [_address] ['ammount'], int (_mdammount), self.dataset [_address] ['time'],int (_mdtime)), 5)
|
||||
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.dataset [_address] ['ts'] = _mdts
|
||||
self.dataset [_address] ['ammount'] = self.dataset [_address] ['ammount'] + int (_mdammount)
|
||||
self.dataset [_address] ['time'] = self.dataset [_address] ['time'] + int (_mdtime)
|
||||
self.db_con.updatemilkdata (self.dataset [_address])
|
||||
else:
|
||||
self.log ("All Ok", 5)
|
||||
self.log ("Alles Ok Speichere Melkdaten", 5)
|
||||
self.db_con.addmilkdata (self.dataset [_address])
|
||||
else:
|
||||
self.log ("All Ok", 5)
|
||||
self.log ("Alles Ok Speichere Melkdaten", 5)
|
||||
self.db_con.addmilkdata (self.dataset [_address])
|
||||
self.dataset [_address] = None
|
||||
else:
|
||||
self.log ("Dataset empty ignoring Milking time", 1)
|
||||
self.log ("Datensatzpuffer leer ignore Melkzeit", 1)
|
||||
|
||||
|
||||
|
||||
@@ -233,13 +249,103 @@ def is_set (x, n):
|
||||
return x & 2**n != 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
bus = can.interface.Bus (channel='can0', bustype='socketcan_native')
|
||||
config = ConfigParser ()
|
||||
config.read ('lactor.cfg')
|
||||
c_dbfile = config.get ('Settings', 'dbfile')
|
||||
if not c_dbfile:
|
||||
print ('No DB File configured')
|
||||
sys.exit (0)
|
||||
c_candev = config.get ('Settings', 'candev')
|
||||
if not c_candev:
|
||||
print ('No CAN Device configured')
|
||||
sys.exit (0)
|
||||
|
||||
dbcon = DB (c_dbfile, '/tmp/talog.sql', logtest, errlogtest)
|
||||
|
||||
bus = can.interface.Bus (channel = c_candev, bustype = 'socketcan_native')
|
||||
a_listener = CanListener ()
|
||||
a_listener.set_db (dbpath = '/opt/data/animaldb.sqlite')
|
||||
a_listener.set_db (dbcon)
|
||||
notifier = can.Notifier (bus, [a_listener])
|
||||
|
||||
try:
|
||||
while True:
|
||||
sleep (1)
|
||||
except KeyboardInterrupt:
|
||||
bus.shutdown ()
|
||||
c_loglevel = int (config.get ('DEBUG', 'loglevel'))
|
||||
|
||||
c_herde = config.get ('HERDE', 'herde')
|
||||
c_herdepath = config.get ('HERDE', 'herdepath').rstrip ('/')
|
||||
if c_herde and not c_herdepath:
|
||||
print ('No Path for HERDE Couppling defined')
|
||||
sys.exit (0)
|
||||
c_herdepath += '/'
|
||||
if c_herdepath and not Path (c_herdepath).exists ():
|
||||
print ('Path to HERDE doesnt exist')
|
||||
sys.exit (0)
|
||||
|
||||
c_herdereadfile = config.get ('HERDE', 'herdereadfile')
|
||||
if c_herde and not c_herdereadfile:
|
||||
print ('No Readfile für 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')
|
||||
sys.exit (0)
|
||||
if c_herde:
|
||||
taurus = TAURUS (dbcon, c_loglevel, c_herdewritefile)
|
||||
|
||||
|
||||
c_animalrecognition = config.get ('Animal Recognition', 'animalrecognition')
|
||||
if c_animalrecognition:
|
||||
c_rfiddev = config.get ('Animal Recognition', 'rfiddev')
|
||||
if not c_rfiddev:
|
||||
print ('No RFID Device configured')
|
||||
sys.exit (0)
|
||||
"""
|
||||
Nedap RFID Reader
|
||||
"""
|
||||
rfid = serial.Serial (port = c_rfiddev,\
|
||||
baudrate = "9600",\
|
||||
bytesize = 8,\
|
||||
parity = "N",\
|
||||
stopbits = 1,\
|
||||
timeout = 0,\
|
||||
xonxoff = 0,\
|
||||
rtscts = 0,\
|
||||
writeTimeout = None)
|
||||
herdefiletslatch = None
|
||||
herdechanged = 0
|
||||
readbuffer = ''
|
||||
online = 0
|
||||
animalnr = ''
|
||||
while 1:
|
||||
if c_herde:
|
||||
if Path (c_herdepath + c_herdereadfile).exists ():
|
||||
_herdets = os.stat (c_herdepath + c_herdereadfile).st_mtime
|
||||
if herdefiletslatch and not herdechanged and herdefiletslatch != _herdets:
|
||||
print ("New Herdefile wait for changes done")
|
||||
herdechanged = 1
|
||||
elif herdefiletslatch and herdechanged and (herdefiletslatch == _herdets) and (time () - _herdets) > 2:
|
||||
print ("Parse File")
|
||||
taurus.parsefile (c_herdepath, c_herdereadfile)
|
||||
herdechanged = 0
|
||||
|
||||
herdefiletslatch = _herdets
|
||||
#Tiererkennung
|
||||
if c_animalrecognition:
|
||||
try:
|
||||
d = rfid.read ()
|
||||
if len (d):
|
||||
readbuffer += d.decode("utf-8")
|
||||
if readbuffer [-2:] == '\r\n':
|
||||
if online:
|
||||
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:
|
||||
bus.shutdown ()
|
||||
rfid.close ()
|
||||
|
||||
|
||||
9
startlactor.sh
Normal file
9
startlactor.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#! /bin/bash
|
||||
while true; do
|
||||
echo "Starting Lactor in `pwd` at `date`" >> /var/log/lactor/startstop.log
|
||||
#echo "BDE restarted" | mail -s "BDE Restart" admin@apc910.finoba.by
|
||||
python3 ./lactor.py `pwd` 2>&1 >> log_`date -Idate`.txt
|
||||
echo "Lactor stopped in `pwd` at `date`" >> /var/log/bde/startstop.log
|
||||
sleep 2
|
||||
done
|
||||
|
||||
Reference in New Issue
Block a user