summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bitvend-bill.py256
-rw-r--r--deployment/ansible.cfg6
-rw-r--r--deployment/hosts2
-rw-r--r--deployment/nginx.site19
-rw-r--r--deployment/playbook.yml22
-rw-r--r--requirements.txt2
6 files changed, 50 insertions, 257 deletions
diff --git a/bitvend-bill.py b/bitvend-bill.py
deleted file mode 100644
index d6795c5..0000000
--- a/bitvend-bill.py
+++ /dev/null
@@ -1,256 +0,0 @@
-import pigpio
-import time
-import struct
-
-from prometheus_client import start_http_server, Counter
-#start_http_server(8000)
-
-coin_counter = Counter('coins_inserted', 'Number of coins inserted into machine')
-purchase_counter = Counter('purchases', 'Number of purchases')
-
-RX_PIN = 4
-TX_PIN = 17
-
-CASHLESS_RESET = 0x10
-CASHLESS_SETUP = 0x11
-CASHLESS_POLL = 0x12
-CASHLESS_VEND = 0x13
-CASHLESS_READER = 0x14
-CASHLESS_REVALUE = 0x15
-
-CASHLESS_EXP = 0x17
-CASHLESS_EXP_REQ_ID = 0x00
-#CASHLESS_EXP_READ = 0x01
-#CASHLESS_EXP_WRITE = 0x02
-CASHLESS_EXP_WRITE_TIME = 0x03
-CASHLESS_EXP_FEATURE_ENABLE = 0x04
-
-BILL_RESET = 0x30
-BILL_SETUP = 0x31
-BILL_POLL = 0x33
-BILL_TYPE = 0x34
-BILL_STACKER = 0x36
-BILL_EXP = 0x37
-BILL_EXP_ID = 0x00
-
-
-# Page 26 - peripheral addresses
-
-pi = pigpio.pi()
-pi.wave_clear()
-pi.set_mode(TX_PIN, pigpio.INPUT)
-
-try:
- pi.bb_serial_read_close(RX_PIN)
-except:
- pass
-
-status = pi.bb_serial_read_open(RX_PIN, 9600, 9)
-
-if status != 0:
- print 'Open failed:', status
- exit(1)
-
-
-def compute_chk(data):
- return reduce(lambda a, b: (a+b)%256, data)
-
-def compute_checksum(cmd, data):
- return reduce(lambda a, b: (a+b)%256, chr(cmd) + data)
-
-class MDBRequest(object):
- timestamp = None
- data = None
- command = None
- processed = False
-
- def __init__(self, command):
- self.timestamp = time.time()
- self.command = command
- self.data = bytearray()
-
- def validate_checksum(self):
- if not self.data:
- return False
- try:
- if self.ack:
- return self.data[-2] == compute_checksum(self.command, self.data[:-2])
- else:
- return self.data[-1] == compute_checksum(self.command, self.data[:-1])
- except:
- return False
- @property
- def ack(self):
- return self.data[-1] == 0x00
-
- def __repr__(self):
- return '<MDBRequest 0x%02x [%s] chk:%r>' % (
- self.command,
- ' '.join(['0x%02x' % b for b in self.data]),
- self.validate_checksum()
- )
-
-class MDBDevice(object):
- base_address = BILL_RESET
- current_request = None
-
- state = 'IDLE'
-
- config_data = [
- 0x01, # READER config data
- 0x01, # Feature level
- 0xff, 0xff, # UNKNOWN
- #0x19, 0x85, # PLN x---DD
- 0x01, # scale factor
- 0x02, # decimal places factor
- 0x01, # 1s response time
- 0x00, # misc options...
- ]
-
- scaling_factor = 50
- bills = [
- 50, 100, 200, 500, 1000, 2000, 5000, 10000,
- 0, 0, 0, 0, 0, 0, 0, 0,
- ]
-
- feed_bills = []
-
- def __init__(self):
- pass
-
- def feed_amount(self, amount):
- if amount % self.scaling_factor:
- raise Exception('Invalid amount')
-
- while amount > 0:
- bills_list = filter(lambda v: v <= amount, self.bills)
- bills_list.sort()
- print (bills_list, amount)
-
- self.feed_bills.append(self.bills.index(bills_list[-1]))
- amount -= bills_list[-1]
-
- def run(self):
- pass
- while True:
- cnt, data = pi.bb_serial_read(RX_PIN)
- for b in range(0, cnt, 2):
- if data[b+1]:
- if self.current_request: # and not self.current_request.processed:
- print(self.current_request)
-
- self.current_request = MDBRequest(data[b])
- elif self.current_request:
- self.current_request.data.append(data[b])
- else:
- print '[unexpected data: %02x]' % (data[b])
-
- if self.current_request and not self.current_request.processed:
- self.process_request(self.current_request)
-
- def process_request(self, req):
- if (req.command & self.base_address) != self.base_address:
- return
-
- if not req.validate_checksum():
- return
-
- if req.command == BILL_RESET:
- req.processed = True
- self.state = 'RESET'
- print 'reset lol'
- self.send([0x100])
-
- elif req.command == BILL_POLL:
- req.processed = True
- print 'poll', self.state
- #self.send([0b10000000], checksum=True)
- if self.state == 'RESET':
- self.send([0b110, 0x100]) # validator was reset
- self.state = 'SETUP'
- elif self.feed_bills:
- self.send([0b10000000 + self.feed_bills[-1]], checksum=True)
- else:
- self.send([0x100])
-
- elif req.command == BILL_SETUP:
- print 'setup', self.state
- req.processed = True
- self.send([
- 0x01, # level
- 0x19, 0x85, # currency
- 0x00, self.scaling_factor, # scaling factor
- 0x02, # decimals
- 0x00, 0x01, # stacker size
- 0xff, 0xff, # security levels
- 0x00, # no escrow
- ] +
- [b / self.scaling_factor for b in self.bills], checksum=True)
- elif req.command == BILL_EXP and req.data[0] == BILL_EXP_ID:
- self.send([
- ord('G'), ord('M'), ord('D'), # manufacturer
- ] +
- [ord('0')] * 12 + # SN
- [ord('0')] * 12 + # Model
- [0x21, 0x37], checksum=True)
- req.processed = True
- elif req.command == BILL_TYPE and len(req.data) == 5:
- req.processed = True
- self.send([0x100]) # just confirm
- elif req.command == BILL_STACKER:
- req.processed = True
- self.send([0b10000000, 0b00000001], checksum=True)
- self.feed_bills.pop()
-
- '''
- elif req.command == CASHLESS_POLL:
- print 'POLL', self.state
- req.processed = True
- if self.state == 'RESET':
- #self.send([0x0a, 0x00], checksum=True)
- self.send([0x00, 0x100])
- self.state = 'IDLE'
- #self.send([0x03, 0x00, 0x10], checksum=True)
- #self.send([0x02, 0x05, ord('x'), ord('D')], checksum=True)
- elif self.state == 'SETUP':
- self.send(self.config_data, checksum=True)
- self.state = 'IDLE'
- elif self.state == 'IDLE':
- self.send([0x100])
-
- elif req.command == CASHLESS_SETUP and len(req.data) == 6 and req.validate_checksum():
- req.processed = True
- print 'VMC setup data:', req.data[1:-1]
- vmc_level, disp_cols, disp_rows, disp_info = req.data[1:-1]
- print 'vmc_level:', vmc_level
- print 'disp_cols:', disp_cols
- print 'disp_rows:', disp_rows
- print 'disp_info:', disp_info
-
- self.send(self.config_data, checksum=True)
-
- self.state = 'SETUP'
- '''
-
- def send(self, data, checksum=False):
- msg = ''.join([struct.pack('<h', n) for n in data])
- if checksum:
- msg += chr(compute_chk(data)) + '\x01'
-
- print(', '.join('%02x' % ord(b) for b in msg))
-
- pi.wave_clear()
- pi.wave_add_serial(TX_PIN, 9600, msg, bb_bits=9, bb_stop=6)
- wid = pi.wave_create()
-
- pi.set_mode(TX_PIN, pigpio.OUTPUT)
- pi.wave_send_once(wid) # transmit serial data
- while pi.wave_tx_busy(): # wait until all data sent
- pass
-
- pi.wave_delete(wid)
- pi.set_mode(TX_PIN, pigpio.INPUT)
-
-dev = MDBDevice()
-dev.feed_amount(150)
-dev.run()
diff --git a/deployment/ansible.cfg b/deployment/ansible.cfg
new file mode 100644
index 0000000..ea22cb2
--- /dev/null
+++ b/deployment/ansible.cfg
@@ -0,0 +1,6 @@
+[defaults]
+remote_user=root
+hostfile=hosts
+
+[ssh_connection]
+pipelining=True
diff --git a/deployment/hosts b/deployment/hosts
new file mode 100644
index 0000000..aa9788e
--- /dev/null
+++ b/deployment/hosts
@@ -0,0 +1,2 @@
+[bitvend]
+vending.waw.hackerspace.pl
diff --git a/deployment/nginx.site b/deployment/nginx.site
new file mode 100644
index 0000000..cd21099
--- /dev/null
+++ b/deployment/nginx.site
@@ -0,0 +1,19 @@
+server {
+ listen 80 default_server;
+ server_name vending.waw.hackerspace.pl;
+
+ location / {
+ proxy_pass http://127.0.0.1:5000;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ }
+
+ listen 443 ssl default_server;
+
+ ssl_certificate /var/lib/dehydrated/certs/vending.waw.hackerspace.pl/fullchain.pem;
+ ssl_certificate_key /var/lib/dehydrated/certs/vending.waw.hackerspace.pl/privkey.pem;
+
+ if ($scheme = http) {
+ return 301 https://$server_name$request_uri;
+ }
+}
diff --git a/deployment/playbook.yml b/deployment/playbook.yml
new file mode 100644
index 0000000..96fbc44
--- /dev/null
+++ b/deployment/playbook.yml
@@ -0,0 +1,22 @@
+- hosts: bitvend
+ tasks:
+ - apt: name="{{ item }}" state=present
+ with_items:
+ - pigpio
+ - python3-pigpio
+ - python3-pip
+ - python3-pillow
+ - nginx
+ - dehydrated
+ - user: name=bitvend home=/var/bitvend system=yes
+ - synchronize: src=../../ dest=/var/bitvend
+ - file: path=/var/bitvend owner=bitvend group=bitvend recurse=yes
+ - pip: requirements=/var/bitvend/requirements.txt executable=/usr/bin/pip3
+ - copy: src=bitvend.service dest=/etc/systemd/system
+ - copy: src=nginx.site dest=/etc/nginx/sites-available/default
+ - service: name=nginx state=reloaded
+ - service: name=pigpiod enabled=yes state=started
+ - service: name=bitvend enabled=yes state=started
+
+ # Cleanup
+ - user: name=pi state=absent
diff --git a/requirements.txt b/requirements.txt
index b7d1cca..253ae77 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,7 +8,7 @@ Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.9.4
MarkupSafe==0.23
-Pillow==4.0.0
+Pillow>=4.0.0
prometheus-client==0.0.18
qrcode==5.3
requests==2.12.4