-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathunified_kasse.py
179 lines (159 loc) · 5.39 KB
/
unified_kasse.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import mysql.connector
from hashlib import sha256
from datetime import datetime
from email_sender import emailSender
import user_config
from mqtt_notify import MqttNotify
import logging
logger = logging.getLogger(__name__)
class Transaction:
def __init__(self, desc, value, date):
self.desc = desc
self.value = value
self.date = datetime.fromtimestamp(date)
def getDate(self):
return self.date
def getValue(self):
return self.value
def getDesc(self):
return self.desc
def toString(self):
return "%s %s %6.2f" % (self.date.strftime('%d.%m.%y %H:%M'), self.desc, self.value)
class UnifiedKasse:
_bankomatDB = None
_cursor = None
def _connect(self):
logger.debug('Tring to connect to internal database')
try:
UnifiedKasse._bankomatDB = mysql.connector.connect(
host = user_config.LOCALDB_HOST,
port = user_config.LOCALDB_PORT,
user = user_config.LOCALDB_USERNAME,
password = user_config.LOCALDB_PASSWORD,
database = user_config.LOCALDB_DATABASE
)
UnifiedKasse._cursor = UnifiedKasse._bankomatDB.cursor(dictionary=True)
UnifiedKasse._cursor.execute('SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED')
for k in ['nfckasse', 'machines', 'donations', 'cards']:
# Updating MQTT values
UnifiedKasse([0], k).getTotal()
return True
except mysql.connector.Error:
logger.exception('Could not connect to internal database')
return False
def __init__(self, uid, source):
self.source = source
self._uid = 0
for i in uid:
self._uid <<= 8
self._uid += i
if UnifiedKasse._bankomatDB is None:
if not self._connect():
raise Exception('UnifiedKasse DB Connection failed')
logger.debug('Initialized UnifiedKasse for uid %08x', uid)
try:
self.ping()
except:
pass
def getSource(self):
return self.source
def isAdmin(self):
logger.debug('Checking if user is admin')
try:
UnifiedKasse._cursor.execute('SELECT uid FROM admins WHERE uid = %s', (self._uid,))
result = self._cursor.fetchone()
return 'uid' in result
except mysql.connector.Error as error:
return False
except TypeError as error:
return False
def getAdminName(self):
logger.debug('Resolving user name')
try:
UnifiedKasse._cursor.execute('SELECT name FROM admins WHERE uid = %s', (self._uid,))
result = self._cursor.fetchone()
return result['name']
except mysql.connector.Error as error:
return None
except TypeError:
return None
def generatePin(pin):
return sha256(pin.encode('utf-8')).hexdigest()
def checkPin(self, pin):
logger.debug('Checking pin')
try:
UnifiedKasse._cursor.execute('SELECT uid FROM admins WHERE uid = %s AND pin = %s', (self._uid, UnifiedKasse.generatePin(pin)))
result = self._cursor.fetchone()
return 'uid' in result
except mysql.connector.Error as error:
logger.exception()
return False
except TypeError as error:
logger.exception('Possibly entered wrong pin')
return False
def getTotal(self):
try:
UnifiedKasse._cursor.execute('SELECT value FROM targets WHERE tname = %s', (self.source,))
result = self._cursor.fetchone()
try:
MqttNotify.getInstance().setKasseTotal(self.source, result['value'])
except:
pass # No connection
return result['value']
except mysql.connector.Error as error:
logger.exception()
return 0
except TypeError:
logger.exception()
return 0
def addValue(self, value, pulses):
try:
UnifiedKasse._cursor.execute('INSERT INTO transactions (uid, value, pulses, sourcedest, dt) VALUES (%s, %s, %s, %s, NOW())', (self._uid, value, pulses, self.source))
UnifiedKasse._cursor.execute('UPDATE targets SET value = value + %s WHERE tname = %s', (value, self.source))
UnifiedKasse._bankomatDB.commit()
total = self.getTotal()
if float(total) > 500 and float(total) - float(value) < 500:
try:
email = emailSender()
email.report('Einzahlungen über 500 Euro', 'Die Einzahlungen für %s liegen über 500 Euro' % (self.source,))
except:
pass
return True
except mysql.connector.Error as error:
logger.exception('Add value for source %s failed: %08x, value %.2f', self.source, self._uid, value)
return False
def mopupValue(self, value):
try:
UnifiedKasse._cursor.execute('INSERT INTO transactions (uid, value, sourcedest, dt) VALUES (%s, %s, %s, NOW())', (self._uid, -value, self.source))
UnifiedKasse._cursor.execute('UPDATE targets SET value = value - %s WHERE tname = %s', (value, self.source))
UnifiedKasse._bankomatDB.commit()
try:
email = emailSender()
email.report('Abschöpfung %s' % (self.source,), "Soeben hat %s eine Abschöpfung in Höhe von %.2f Euro vorgenommen" % (self.getAdminName(), value))
except:
pass
self.getTotal() # update MQTT sensors
return True
except mysql.connector.Error as error:
logger.exception('Mopup failed')
return False
def start(self):
pass
def disconnect(self):
pass
def ping(self):
try:
UnifiedKasse._bankomatDB.ping(True)
return True
except mysql.connector.errors.OperationalError: # lost connection
return self._connect()
except mysql.connector.errors.InterfaceError: # lost connection
return self._connect()
if __name__ == '__main__':
ukasse = UnifiedKasse(user_config.UID_TEST, 'donations')
print('User is admin: %d' % (ukasse.isAdmin(), ))
print('Total value: %.2f' % (ukasse.getTotal(), ))
print(ukasse.ping())
import getpass
pin = getpass.getpass('Generate pin hash (4 digits): ')
print(UnifiedKasse.generatePin(pin))