beielipi/bin/beielimon.py

134 lines
3.8 KiB
Python
Executable File

#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# vim: expandtab sw=4 ts=4 sts=4:
#
# Beehive-Monitoring with SMS Alerts and Data-Upload to
# Webservice.
#
# Author: Joerg Lehmann, nbit Informatik GmbH
#
"""Beehive Monitoring"""
from __future__ import print_function
import gammu.smsd
import sys
import serial
import time
import yaml
# Read Configuration from YAML-File
with open("beielimon-config.yaml", 'r') as stream:
try:
config_data = yaml.load(stream)
except yaml.YAMLError as exc:
print(exc)
# Constants
INVALID_VALUE = -999
# Interface to gammu-smsd
smsd = gammu.smsd.SMSD('/etc/gammu-smsdrc')
class Scale(object):
def __init__(self):
self.last_values = []
def __del__(self):
pass
def AppendReading(self,weigh_in_gram):
self.last_values.append(weigh_in_gram)
if len(self.last_values) > config_data['number_of_samples']:
self.last_values = self.last_values[1:]
print('DEBUG WEIGHT: %d' % (weigh_in_gram))
print(self.last_values)
def Read(self):
pass
def SwarmAlarm(self):
return (self.GetWeighLoss() > config_data['swarm_alarm_threshold_gram'])
def ResetValues(self):
self.last_values = []
def GetLastValue(self):
return (self.last_values or [0])[-1]
def GetWeighLoss(self):
last_value = self.GetLastValue()
max_value = max(self.last_values or [0])
print('BBB: ',max_value,last_value)
return (max_value - last_value)
class ScaleUSB_PCE(Scale):
def __init__(self,serial_int):
Scale.__init__(self)
self.ser = serial_int
def Read(self):
res = INVALID_VALUE
self.ser.write('Sx\r\n')
weight_string = self.ser.readline()
if len(weight_string) == 16:
if (weight_string[12:13] == 'g'):
try:
res = int(weight_string[2:11])
except:
print('DEBUG WEIGHT STRING IS NOT AN INTEGER: %s' % (weight_string[2:11]))
else:
print('DEBUG WEIGHT STRING SHOULD BE IN GRAMS: but is [%s]' % (weight_string[12:13]))
else:
print('DEBUG WEIGHT STRING SHOULD BE 16 DIGITS: but is %d' % (len(weight_string)))
if res != INVALID_VALUE:
self.AppendReading(res)
class ScaleDummy(Scale):
def __init__(self,serial_int):
pass
def Read(self):
pass
def send_sms(phonenumbers , text):
for phonenumber in phonenumbers:
message = {
'Text': text,
'SMSC': {'Location': 1},
'Number': phonenumber
}
smsd.InjectSMS([message])
def main():
scales = []
for scale_interface in config_data['scale_interfaces']:
if scale_interface == 'usb_pce':
ser = serial.Serial(port='/dev/ttyUSB0',
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_EVEN,
timeout=20000)
scale=ScaleUSB_PCE(ser)
scales.append(scale)
# Main Loop
while True:
for scale in scales:
scale.Read()
if scale.SwarmAlarm():
date_time = time.strftime("%d.%m.%Y %H:%M:%S")
last_value = scale.GetLastValue()
weigh_loss = scale.GetWeighLoss()
sms_message = '*** Schwarmalarm ***\nDatum/Zeit: \nLetztes Gewicht [g]: %d\nGewichtsverlust [g]: %d' % (date_time,last_value,weigh_loss)
print(config_data['sms_alert_phonenumbers'],sms_message)
send_sms(config_data['sms_alert_phonenumbers'],sms_message)
scale.ResetValues()
time.sleep(config_data['read_scale_interval_sec'])
if __name__ == "__main__":
main()