Skip to content

Commit

Permalink
[IMP] point_of_sale: posbox upgrade to stretch / python3
Browse files Browse the repository at this point in the history
- transform odoo.py -> odoo-bin / recent branches + pip3 packages
- deactivate wpa_supplicant when starting dhcpcd automatically
- postgresql create clusters manually
- latest stretch raspbian image / add versatile-db.ptb for kernel-qemu
- ifconfig output change
- upgrade hw_-modules:
    hw_escpos: to python3
    hw_posbox_homepage: to v11: csrf does not work as it needs a database
    hw_posbox_upgrade: to python3 decode utf-8
    hw_scale: to python3
    hw_proxy: to python3

With the commit, the posbox will also work on the new Raspberry Pi 3b+
  • Loading branch information
jco-odoo committed Jul 13, 2018
1 parent e8821f0 commit 7d34f02
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 75 deletions.
26 changes: 19 additions & 7 deletions addons/hw_escpos/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import os.path
import subprocess
import time
import netifaces as ni
import traceback

try:
Expand All @@ -29,9 +30,10 @@
usb = None

from odoo import http, _

from odoo.addons.hw_proxy.controllers import main as hw_proxy

from uuid import getnode as get_mac

_logger = logging.getLogger(__name__)

# workaround https://bugs.launchpad.net/openobject-server/+bug/947231
Expand Down Expand Up @@ -196,10 +198,18 @@ def push_task(self,task, data = None):
def print_status(self,eprint):
localips = ['0.0.0.0','127.0.0.1','127.0.1.1']
hosting_ap = os.system('pgrep hostapd') == 0
ssid = subprocess.check_output('iwconfig 2>&1 | grep \'ESSID:"\' | sed \'s/.*"\\(.*\\)"/\\1/\'', shell=True).rstrip()
mac = subprocess.check_output('ifconfig | grep -B 1 \'inet addr\' | grep -o \'HWaddr .*\' | sed \'s/HWaddr //\'', shell=True).rstrip()
ips = [ c.split(':')[1].split(' ')[0] for c in subprocess.check_output("/sbin/ifconfig").split('\n') if 'inet addr' in c ]
ips = [ ip for ip in ips if ip not in localips ]
ssid = subprocess.check_output('iwconfig 2>&1 | grep \'ESSID:"\' | sed \'s/.*"\\(.*\\)"/\\1/\'', shell=True).decode('utf-8').rstrip()
mac = get_mac()
h = iter(hex(mac)[2:].zfill(12))
mac = ":".join(i + next(h) for i in h)
interfaces = ni.interfaces()
ips = []
for iface_id in interfaces:
iface_obj = ni.ifaddresses(iface_id)
ifconfigs = iface_obj.get(ni.AF_INET, [])
for conf in ifconfigs:
if conf.get('addr'):
ips.append(conf.get('addr'))
eprint.text('\n\n')
eprint.set(align='center',type='b',height=2,width=2)
eprint.text('PosBox Status\n')
Expand All @@ -221,8 +231,10 @@ def print_status(self,eprint):
eprint.text(ip+'\n')

if len(ips) >= 1:
eprint.text('\nMAC Address:\n' + mac + '\n')
eprint.text('\nHomepage:\nhttp://'+ips[0]+':8069\n')
ips_filtered = [i for i in ips if i != '127.0.0.1']
main_ips = ips_filtered and ips_filtered[0] or '127.0.0.1'
eprint.text('\nMAC Address:\n' + str(mac) + '\n')
eprint.text('\nHomepage:\nhttp://' + main_ips + ':8069\n')

eprint.text('\n\n')
eprint.cut()
Expand Down
35 changes: 18 additions & 17 deletions addons/hw_escpos/escpos/escpos.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import math
import re
import traceback
import codecs
from hashlib import md5

from PIL import Image
Expand Down Expand Up @@ -318,9 +319,9 @@ def _check_image_size(self, size):
else:
image_border = 32 - (size % 32)
if (image_border % 2) == 0:
return (image_border / 2, image_border / 2)
return (int(image_border / 2), int(image_border / 2))
else:
return (image_border / 2, (image_border / 2) + 1)
return (int(image_border / 2), int((image_border / 2) + 1))

def _print_image(self, line, size):
""" Print formatted image """
Expand All @@ -330,8 +331,8 @@ def _print_image(self, line, size):


self._raw(S_RASTER_N)
buffer = "%02X%02X%02X%02X" % (((size[0]/size[1])/8), 0, size[1], 0)
self._raw(buffer.decode('hex'))
buffer = b"%02X%02X%02X%02X" % (int((size[0]/size[1])/8), 0, size[1], 0)
self._raw(codecs.decode(buffer, 'hex'))
buffer = ""

while i < len(line):
Expand All @@ -340,7 +341,7 @@ def _print_image(self, line, size):
i += 8
cont += 1
if cont % 4 == 0:
self._raw(buffer.decode("hex"))
self._raw(codecs.decode(buffer, "hex"))
buffer = ""
cont = 0

Expand All @@ -349,7 +350,7 @@ def _raw_print_image(self, line, size, output=None ):
i = 0
cont = 0
buffer = ""
raw = ""
raw = b""

def __raw(string):
if output:
Expand All @@ -358,8 +359,8 @@ def __raw(string):
self._raw(string)

raw += S_RASTER_N
buffer = "%02X%02X%02X%02X" % (((size[0]/size[1])/8), 0, size[1], 0)
raw += buffer.decode('hex')
buffer = "%02X%02X%02X%02X" % (int((size[0]/size[1])/8), 0, size[1], 0)
raw += codecs.decode(buffer, 'hex')
buffer = ""

while i < len(line):
Expand All @@ -368,7 +369,7 @@ def __raw(string):
i += 8
cont += 1
if cont % 4 == 0:
raw += buffer.decode("hex")
raw += codecs.decode(buffer, 'hex')
buffer = ""
cont = 0

Expand Down Expand Up @@ -433,14 +434,14 @@ def print_base64_image(self,img):

print('print_b64_img')

id = md5(img.encode('utf-8')).digest()
id = md5(img).digest()

if id not in self.img_cache:
print('not in cache')

img = img[img.find(',')+1:]
f = io.BytesIO('img')
f.write(base64.decodestring(img))
img = img[img.find(b',')+1:]
f = io.BytesIO(b'img')
f.write(base64.decodebytes(img))
f.seek(0)
img_rgba = Image.open(f)
img = Image.new('RGB', img_rgba.size, (255,255,255))
Expand Down Expand Up @@ -677,7 +678,7 @@ def print_elem(stylestack, serializer, elem, indent=0):

elif elem.tag == 'img':
if 'src' in elem.attrib and 'data:' in elem.attrib['src']:
self.print_base64_image(elem.attrib['src'])
self.print_base64_image(bytes(elem.attrib['src'], 'utf-8'))

elif elem.tag == 'barcode' and 'encoding' in elem.attrib:
serializer.start_block(stylestack)
Expand Down Expand Up @@ -797,19 +798,19 @@ def encode_char(char):
(encoding, _) = remaining.popitem()
else:
encoding = 'cp437'
encoded = '\xb1' # could not encode, output error character
encoded = b'\xb1' # could not encode, output error character
break;

if encoding != self.encoding:
# if the encoding changed, remember it and prefix the character with
# the esc-pos encoding change sequence
self.encoding = encoding
encoded = encodings[encoding] + encoded
encoded = bytes(encodings[encoding], 'utf-8') + encoded

return encoded

def encode_str(txt):
buffer = ''
buffer = b''
for c in txt:
buffer += encode_char(c)
return buffer
Expand Down
6 changes: 3 additions & 3 deletions addons/hw_posbox_homepage/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def wifi(self):
"""
return wifi_template

@http.route('/wifi_connect', type='http', auth='none', cors='*')
@http.route('/wifi_connect', type='http', auth='none', cors='*', csrf=False)
def connect_to_wifi(self, essid, password, persistent=False):
if persistent:
persistent = "1"
Expand All @@ -171,7 +171,7 @@ def connect_to_wifi(self, essid, password, persistent=False):
subprocess.call(['/home/pi/odoo/addons/point_of_sale/tools/posbox/configuration/connect_to_wifi.sh', essid, password, persistent])
return "connecting to " + essid

@http.route('/wifi_clear', type='http', auth='none', cors='*')
@http.route('/wifi_clear', type='http', auth='none', cors='*', csrf=False)
def clear_wifi_configuration(self):
os.system('/home/pi/odoo/addons/point_of_sale/tools/posbox/configuration/clear_wifi_configuration.sh')
return "configuration cleared"
Expand Down Expand Up @@ -244,7 +244,7 @@ def remote_connect(self):
"""
return ngrok_template

@http.route('/enable_ngrok', type='http', auth='none', cors='*')
@http.route('/enable_ngrok', type='http', auth='none', cors='*', csrf=False)
def enable_ngrok(self, auth_token):
if subprocess.call(['pgrep', 'ngrok']) == 1:
subprocess.Popen(['ngrok', 'tcp', '-authtoken', auth_token, '-log', '/tmp/ngrok.log', '22'])
Expand Down
2 changes: 1 addition & 1 deletion addons/hw_posbox_upgrade/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
</p>
<pre>
"""
upgrade_template += subprocess.check_output("git --work-tree=/home/pi/odoo/ --git-dir=/home/pi/odoo/.git log -1", shell=True).replace("\n", "<br/>")
upgrade_template += subprocess.check_output("git --work-tree=/home/pi/odoo/ --git-dir=/home/pi/odoo/.git log -1", shell=True).decode('utf-8').replace("\n", "<br/>")
upgrade_template += """
</pre>
<div class='centering'>
Expand Down
15 changes: 9 additions & 6 deletions addons/hw_proxy/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
"0424:9514", # Standard Microsystem Corp. Builtin Ethernet module
"1d6b:0002", # Linux Foundation 2.0 root hub
"0424:ec00", # Standard Microsystem Corp. Other Builtin Ethernet module
"0424:2514", # Standard Microsystems Corp. USB 2.0 Hub (rpi3b+)
"0424:7800", # Standard Microsystems Corp. (rpi3b+)
}


Expand Down Expand Up @@ -100,15 +102,16 @@ def status_http(self, debug=None, **kwargs):
"""
if debug is None:
resp += """(<a href="/hw_proxy/status?debug">debug version</a>)"""
devices = subprocess.check_output("lsusb").split('\n')
devices = subprocess.check_output("lsusb").decode('utf-8').split('\n')
count = 0
resp += "<div class='devices'>\n"
for device in devices:
device_name = device[device.find('ID')+2:]
device_id = device_name.split()[0]
if not (device_id in BANNED_DEVICES):
resp += "<div class='device' data-device='"+device+"'>"+device_name+"</div>\n"
count += 1
if device_name: # to avoid last empty line
device_id = device_name.split()[0]
if not (device_id in BANNED_DEVICES):
resp += "<div class='device' data-device='"+device+"'>"+device_name+"</div>\n"
count += 1

if count == 0:
resp += "<div class='device'>No USB Device Found</div>"
Expand All @@ -124,7 +127,7 @@ def status_http(self, debug=None, **kwargs):
%s
</pre>
""" % subprocess.check_output('lsusb -v', shell=True)
""" % subprocess.check_output('lsusb -v', shell=True).decode('utf-8')

return request.make_response(resp,{
'Cache-Control': 'no-cache',
Expand Down
28 changes: 14 additions & 14 deletions addons/hw_scale/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
def _toledo8217StatusParse(status):
""" Parse a scale's status, returning a `(weight, weight_info)` pair. """
weight, weight_info = None, None
stat = ord(status[status.index('?') + 1])
stat = status[status.index(b'?') + 1]
if stat == 0:
weight_info = 'ok'
else:
Expand Down Expand Up @@ -68,17 +68,17 @@ def _toledo8217StatusParse(status):
parity=serial.PARITY_EVEN,
timeout=1,
writeTimeout=1,
weightRegexp="\x02\\s*([0-9.]+)N?\\r",
statusRegexp="\x02\\s*(\\?.)\\r",
weightRegexp=b"\x02\\s*([0-9.]+)N?\\r",
statusRegexp=b"\x02\\s*(\\?.)\\r",
statusParse=_toledo8217StatusParse,
commandDelay=0.2,
weightDelay=0.5,
newWeightDelay=0.2,
commandTerminator='',
weightCommand='W',
zeroCommand='Z',
tareCommand='T',
clearCommand='C',
commandTerminator=b'',
weightCommand=b'W',
zeroCommand=b'Z',
tareCommand=b'T',
clearCommand=b'C',
emptyAnswerValid=False,
autoResetWeight=False,
)
Expand All @@ -98,15 +98,15 @@ def _toledo8217StatusParse(status):
weightRegexp=r"\s*([0-9.]+)kg", # LABEL format 3 + KG in the scale settings, but Label 1/2 should work
statusRegexp=None,
statusParse=None,
commandTerminator="\r\n",
commandTerminator=b"\r\n",
commandDelay=0.2,
weightDelay=0.5,
newWeightDelay=5, # AZExtra beeps every time you ask for a weight that was previously returned!
# Adding an extra delay gives the operator a chance to remove the products
# before the scale starts beeping. Could not find a way to disable the beeps.
weightCommand='P',
zeroCommand='Z',
tareCommand='T',
weightCommand=b'P',
zeroCommand=b'Z',
tareCommand=b'T',
clearCommand=None, # No clear command -> Tare again
emptyAnswerValid=True, # AZExtra does not answer unless a new non-zero weight has been detected
autoResetWeight=True, # AZExtra will not return 0 after removing products
Expand Down Expand Up @@ -165,8 +165,8 @@ def _get_raw_response(self, connection):
if not char:
break
else:
answer.append(char)
return ''.join(answer)
answer.append(bytes(char))
return b''.join(answer)

def _parse_weight_answer(self, protocol, answer):
""" Parse a scale's answer to a weighing request, returning
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@ function connect () {
if [ -z "${PASSWORD}" ] ; then
sudo iwconfig wlan0 essid "${ESSID}"
else
sudo wpa_passphrase "${ESSID}" "${PASSWORD}" > "${WPA_PASS_FILE}"
# Necessary in stretch: https://www.raspberrypi.org/forums/viewtopic.php?t=196927
sudo cp /etc/wpa_supplicant/wpa_supplicant.conf "${WPA_PASS_FILE}"
chmod 777 ${WPA_PASS_FILE}
sudo wpa_passphrase "${ESSID}" "${PASSWORD}" >> "${WPA_PASS_FILE}"
sudo wpa_supplicant -B -i wlan0 -c "${WPA_PASS_FILE}"
fi

sudo systemctl daemon-reload
sudo service dhcpcd restart

# give dhcp some time
timeout 30 sh -c 'until ifconfig wlan0 | grep "inet addr:" ; do sleep 0.1 ; done'
timeout 30 sh -c 'until ifconfig wlan0 | grep "inet " ; do sleep 0.1 ; done'
TIMEOUT_RETURN=$?

if [ ${TIMEOUT_RETURN} -eq 124 ] && [ -z "${NO_AP}" ] ; then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

CURRENT_WIFI_NETWORK_FILE="/tmp/current_wifi_network.txt"
while true ; do
if [ -z "$(cat <(ifconfig eth0) <(ifconfig wlan0) | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}';)" ] ; then
if [ -z "$(cat <(ifconfig eth0) <(ifconfig wlan0) | grep "inet ";)" ] ; then
ESSID=$(head -n 1 "${CURRENT_WIFI_NETWORK_FILE}" | tr -d '\n')
PASSWORD=$(tail -n 1 "${CURRENT_WIFI_NETWORK_FILE}" | tr -d '\n')

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

FORCE_HOST_AP="${1}"
WIRED_IP=$(ifconfig eth0 | grep "inet addr" | awk -F: '{print $2}' | awk '{print $1}';)
WIRED_IP=$(python3 -c "import netifaces as ni; print(ni.ifaddresses('eth0').get(ni.AF_INET) and ni.ifaddresses('eth0')[ni.AF_INET][0]['addr'] or '')")
WIFI_NETWORK_FILE="/home/pi/wifi_network.txt"

# if there is no wired ip, attempt to start an AP through wireless interface
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ slaac private
# A hook script is provided to lookup the hostname if not set by the DHCP
# server, but it should not be run by default.
nohook lookup-hostname
# stretch: we do not want to start wpa_supplicant as our script starts wpa_supplicant itself
nohook wpa_supplicant

# dhcpcd will assign zeroconf 169.254.*.* addresses when
# it can't connect, which we don't want
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
. /lib/lsb/init-functions

PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
DAEMON=/home/pi/odoo/odoo.py
DAEMON=/home/pi/odoo/odoo-bin
NAME=odoo
DESC=odoo
CONFIG=/home/pi/odoo/addons/point_of_sale/tools/posbox/configuration/odoo.conf
Expand Down
Loading

0 comments on commit 7d34f02

Please sign in to comment.