Skip to content
Snippets Groups Projects
Commit b91b6a57 authored by Benjamin Bertrand's avatar Benjamin Bertrand
Browse files

Removed client

Client moved to its own repository (ics-inventory-client)
parent c6866fb5
No related branches found
No related tags found
No related merge requests found
......@@ -2,7 +2,6 @@
**/*.swp
**/__pycache__
settings*.cfg
client
data
postgres
Jenkinsfile
......
ICS inventory
=============
ICS inventory proof of concept.
ICS inventory web server.
Development
......@@ -76,29 +76,3 @@ To restore the database::
$ gunzip -c inventory_db.dump.g | docker run --rm --link inventory_postgres:postgres --net inventory_default
-e PGPASSWORD="<inventory_password>" -i postgres:9.6 psql -h postgres -U inventory inventory_db
Client
------
The `pyscan.py` client can be found under the "client" directory.
You should first create a configuration file::
$ cat ~/.pyscan.yml
device: /dev/tty.usbmodem1421
url: http://localhost:8000/api
username: yourusername
To install the requirements, conda_ is recommended::
$ cd client
$ conda env create -n pyscan
$ source activate pyscan
Run::
$ python pyscan.py
.. _conda: https://conda.io/miniconda.html
name: pyscan
channels: !!python/tuple
- conda-forge
- defaults
dependencies:
- conda-forge::ca-certificates=2017.4.17=0
- conda-forge::certifi=2017.4.17=py36_0
- conda-forge::chardet=3.0.2=py36_1
- conda-forge::click=6.7=py36_0
- conda-forge::idna=2.5=py36_0
- conda-forge::ncurses=5.9=10
- conda-forge::openssl=1.0.2l=0
- conda-forge::pip=9.0.1=py36_0
- conda-forge::python=3.6.1=3
- conda-forge::pyyaml=3.12=py36_1
- conda-forge::readline=6.2=0
- conda-forge::requests=2.18.1=py36_0
- conda-forge::setuptools=33.1.1=py36_0
- conda-forge::sqlite=3.13.0=1
- conda-forge::tk=8.5.19=1
- conda-forge::urllib3=1.21.1=py36_0
- conda-forge::wheel=0.29.0=py36_0
- conda-forge::xz=5.2.2=0
- conda-forge::yaml=0.1.6=0
- conda-forge::zlib=1.2.11=0
- pip:
- daiquiri==1.2.1
- pyserial==3.3
import os
import logging
import time
import click
import daiquiri
import requests
import serial
import yaml
from collections import namedtuple
QRCode = namedtuple('QRCode', 'table id name')
daiquiri.setup(level=logging.DEBUG)
# logger = daiquiri.getLogger(__name__)
logger = daiquiri.getLogger('pyscan')
def get_config(filename):
with open(filename) as f:
config = yaml.load(f)
return config
def get_token(url, username):
password = click.prompt('Please enter your password', hide_input=True)
payload = {'username': username, 'password': password}
r = requests.post(url + '/login', json=payload)
r.raise_for_status()
logger.info(f'Successfully logged in to {url}!')
return r.json()['access_token']
def save_item(url, token, item):
headers = {'Authorization': f'Bearer {token}'}
r = requests.post(url + '/items', json=item, headers=headers)
r.raise_for_status()
def save_items(url, token, items):
for item in items:
try:
save_item(url, token, item)
except requests.exceptions.HTTPError as err:
logger.warning(err)
else:
logger.info(f'Item saved: {item}')
class Scanner:
def __init__(self, device, url, token):
self.device = device
self.url = url
self.token = token
self.items = []
self._manufacturer = None
self._model = None
self._location = None
self._status = None
def process_qrcode(self, qrcode):
if qrcode.table in ('manufacturer', 'model', 'location', 'status'):
logger.info(f'Setting {qrcode.table} to {qrcode.name}')
setattr(self, '_' + qrcode.table, qrcode.name)
elif qrcode.table == 'action':
if qrcode.name == 'Discard last':
try:
item = self.items.pop()
except IndexError:
logger.warning('No item to remove!')
else:
logger.info(f'Item {item} discarded')
elif qrcode.name == 'Clear attributes':
logger.info('Clearing manufacturer/model/location/status')
self._manufacturer = None
self._model = None
self._location = None
self._status = None
elif qrcode.name == 'Save to db':
logger.info('Saving all items to database')
save_items(self.url, self.token, self.items)
self.items = []
else:
logger.warning(f'Unknown action: {qrcode.name}')
else:
logger.warning(f'Unknown table: {qrcode.table}')
def process_serial_number(self, serial_number):
item = {'serial_number': serial_number,
'manufacturer': self._manufacturer,
'model': self._model,
'location': self._location,
'status': self._status,
}
logger.info(f'Creating item: {item}')
self.items.append(item)
def parse(self, line):
logger.debug(line)
try:
qrcode = QRCode(*line.split(','))
except TypeError:
# Assume this is a serial number
self.process_serial_number(line)
else:
self.process_qrcode(qrcode)
def run(self):
logger.debug(self.device)
ser = serial.Serial(self.device, 115200)
while (True):
if ser.in_waiting > 0:
line = ser.readline()
self.parse(line.decode('ascii').strip())
time.sleep(0.1)
@click.command()
@click.option('--conf', '-c', default='~/.pyscan.yml',
help='Configuration file [default: "~/pyscan.yml"]')
def scan(conf):
filename = os.path.expanduser(conf)
config = get_config(filename)
url = config['url']
username = config['username']
token = get_token(url, username)
scanner = Scanner(config['device'], url, token)
scanner.run()
if __name__ == '__main__':
scan()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment