344 lines
13 KiB
HTML
344 lines
13 KiB
HTML
{% extends "base.html" %}
|
|
{% load static %}
|
|
|
|
{% block additional_css %}
|
|
{% endblock %}
|
|
|
|
{% block title %}Smartphone Scanner{% endblock %}
|
|
|
|
{% block content %}
|
|
<style>
|
|
#interactive canvas { position: absolute; left: 0; }
|
|
</style>
|
|
|
|
<div class="container" >
|
|
<div class="row" id="video-button-content">
|
|
<div class="col-1">
|
|
<a class="btn btn-primary" id="startButton">Start</a>
|
|
</div>
|
|
<div class="col-1">
|
|
<a class="btn btn-outline-primary" id="resetButton">Reset</a>
|
|
</div>
|
|
<div class="col-1">
|
|
<a class="btn btn-outline-primary" id="clearOverlayButton">Clear</a>
|
|
</div>
|
|
</div>
|
|
<div class="row" id="video-content">
|
|
<div id="interactive" class="viewport col-12" style="position: relative;">
|
|
<!-- QuaggaJS will populate this element -->
|
|
</div>
|
|
<!--
|
|
<div class="col-8">
|
|
<video id="video" autoplay="true" width="640" height="480" style="border: 1px solid gray"></video>
|
|
</div>-->
|
|
</div>
|
|
<div class="row" id="control-content">
|
|
<div class="col-6" id="sourceSelectPanel" style="display:none">
|
|
<div>
|
|
<label for="sourceSelect">Change video source:</label>
|
|
<select id="sourceSelect" style="max-width:400px"></select>
|
|
</div>
|
|
</div>
|
|
<div class="col-6" id="scan-result-panel" style="display:none">
|
|
<div>
|
|
<label>Scan:</label>
|
|
<pre><code id="result"></code></pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script type="text/javascript" src="{% static 'quagga/dist/quagga.js' %}"></script>
|
|
<script type="text/javascript">
|
|
function beep() {
|
|
var audio = new Audio("{% static 'sound/beep.mp3' %}");
|
|
audio.volume = 0.02;
|
|
console.log("Audio play {% static 'sound/beep.mp3' %}");
|
|
audio.play();
|
|
}
|
|
|
|
function clearCanvas() {
|
|
canvas = document.querySelector('#interactive .drawingBuffer');
|
|
drawing = (canvas != null) ? canvas.getContext('2d') : null;
|
|
console.log('Clearing canvas, drawing=' + drawing + ', canvas=' + canvas);
|
|
if (drawing != null) {
|
|
drawing.clearRect(0, 0, canvas.width, canvas.height);
|
|
console.log('Clearing done');
|
|
}
|
|
}
|
|
|
|
console.log('detected HW concurrency: ' + self.navigator.hardwareConcurrency);
|
|
|
|
window.addEventListener('load', function () {
|
|
let selectedDeviceId;
|
|
let lastScanResult = '';
|
|
let config = {
|
|
inputStream: {
|
|
name: "Live",
|
|
type: "LiveStream",
|
|
constraints: {
|
|
facingMode: "environment",
|
|
},
|
|
|
|
target: document.getElementById('interactive'),
|
|
/*area: {
|
|
top: '0%',
|
|
bottom: '0%',
|
|
left: '0%',
|
|
right: '0%'
|
|
},*/
|
|
},
|
|
//numOfWorkers: 4,
|
|
locate: true,
|
|
debug: true,
|
|
frequency: 20,
|
|
decoder: {
|
|
readers: ["code_128_reader"],
|
|
debug: {
|
|
drawScanline: false,
|
|
drawBoundingBox: false,
|
|
showPattern: false,
|
|
showFrequency: false
|
|
},
|
|
multiple: false
|
|
},
|
|
locator: {
|
|
halfSample: false,
|
|
patchSize: "x-large", // x-small, small, medium, large, x-large
|
|
debug: {
|
|
/*showCanvas: true,*/
|
|
showPatches: false,
|
|
showFoundPatches: false,
|
|
showSkeleton: false,
|
|
showLabels: false,
|
|
showPatchLabels: false,
|
|
showRemainingPatchLabels: false,
|
|
boxFromPatches: {
|
|
showTransformed: false,
|
|
showTransformedBox: false,
|
|
showBB: true
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
function quagga_init() {
|
|
Quagga.init(config, function(err) {
|
|
if (err) {
|
|
console.log(err);
|
|
return;
|
|
}
|
|
console.log("Initialization finished. Ready to start");
|
|
Quagga.start();
|
|
Quagga.onDetected(function(data) {
|
|
code = data.codeResult.code;
|
|
console.log('Got scan: ' + code);
|
|
if (code && lastScanResult !== code) {
|
|
lastScanResult = code;
|
|
console.log('Got scan (cont.): ' + lastScanResult);
|
|
document.querySelector('#result').textContent = lastScanResult;
|
|
// document.getElementById('result').textContent = lastScanResult
|
|
beep();
|
|
useScannedText(lastScanResult);
|
|
console.log(data);
|
|
canvas = document.querySelector('#interactive .drawingBuffer');
|
|
drawing = canvas.getContext('2d');
|
|
drawing.clearRect(0, 0, canvas.width, canvas.height);
|
|
drawing.beginPath();
|
|
drawing.moveTo(data.line[0].x, data.line[0].y);
|
|
drawing.lineTo(data.line[1].x, data.line[1].y);
|
|
drawing.lineWidth = 2;
|
|
drawing.strokeStyle = 'yellow';
|
|
drawing.closePath();
|
|
drawing.stroke();
|
|
setTimeout(clearCanvas, 3000);
|
|
} else if (code) {
|
|
console.log('... scan again');
|
|
}
|
|
});
|
|
/*
|
|
Quagga.onProcessed(function(data) {
|
|
canvas = document.querySelector('#interactive .drawingBuffer');
|
|
if (canvas != null) {
|
|
context = canvas.getContext('2d');
|
|
if (context) {
|
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
}
|
|
}
|
|
});*/
|
|
});
|
|
}
|
|
|
|
quagga_init();
|
|
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
|
|
console.log("enumerateDevices() not supported.");
|
|
return;
|
|
}
|
|
Quagga.CameraAccess.enumerateVideoDevices()
|
|
.then(function(devices) {
|
|
const sourceSelect = document.getElementById('sourceSelect');
|
|
selectedDeviceId = devices[0].deviceId; // default
|
|
if (devices.length > 1) {
|
|
devices.forEach(function(device) {
|
|
console.log(device.kind + ": " + device.label + " id=" + device.deviceId);
|
|
const sourceOption = document.createElement('option');
|
|
sourceOption.text = device.label;
|
|
sourceOption.value = device.deviceId;
|
|
sourceSelect.appendChild(sourceOption);
|
|
});
|
|
sourceSelect.onchange = () => {
|
|
selectedDeviceId = sourceSelect.value;
|
|
config.inputStream.constraints.deviceId = selectedDeviceId;
|
|
Quagga.stop();
|
|
quagga_init();
|
|
}
|
|
const sourceSelectPanel = document.getElementById('sourceSelectPanel');
|
|
sourceSelectPanel.style.display = 'block';
|
|
}
|
|
document.getElementById('startButton').addEventListener('click', () => {
|
|
beep();
|
|
Quagga.start();
|
|
console.log(`Started scan from camera with id ${selectedDeviceId}`)
|
|
})
|
|
|
|
document.getElementById('resetButton').addEventListener('click', () => {
|
|
document.getElementById('result').textContent = '';
|
|
Quagga.stop();
|
|
console.log('Reset/stopped.')
|
|
})
|
|
|
|
document.getElementById('clearOverlayButton').addEventListener('click', () => {
|
|
clearCanvas();
|
|
})
|
|
})
|
|
.catch(function(err) {
|
|
console.log(err);
|
|
});
|
|
|
|
});
|
|
</script>
|
|
<hr />
|
|
<div class="row mb-3">
|
|
<div class="col-8">
|
|
<div class="input-group">
|
|
<input class="form-control" type="text" maxlength="40" id="container_id" placeholder="Container ID">
|
|
<input class="form-control" type="text" maxlength="40" id="asset_id" placeholder="Asset ID">
|
|
</div>
|
|
</div>
|
|
<div class="col-2">
|
|
<div class="input-group">
|
|
<input class="btn btn-primary" id="book-in-button" type="button" value="+Book">
|
|
<input class="btn btn-primary" id="book-out-button" type="button" value="-Book">
|
|
</div>
|
|
</div>
|
|
<div class="col-8">
|
|
<div class="input-group">
|
|
<textarea class="form-control" readonly="readonly" rows="4" id="container_details"></textarea>
|
|
<textarea class="form-control" readonly="readonly" rows="4" id="asset_details"></textarea>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row">
|
|
<div class="input-group">
|
|
<textarea class="form-control mb-2" id="chat-log" cols="100" rows="10"></textarea>
|
|
<input class="btn btn-secondary" id="clear-chat-area" type="button" value="Clear">
|
|
</div>
|
|
</div>
|
|
<script>
|
|
var containerIsValid = false;
|
|
var assetIsValid = false;
|
|
|
|
async function getObjectInfo(url) {
|
|
const response = await fetch(url);
|
|
const object_json = response.json();
|
|
return object_json;
|
|
}
|
|
|
|
async function getContainerInfo(containerId) {
|
|
document.querySelector('#container_id').value = containerId;
|
|
url = '/api/containers?named_id=' + containerId;
|
|
document.querySelector('#container_details').value = 'Trying ' + url;
|
|
const container = await getObjectInfo(url);
|
|
if (container.count >= 1) {
|
|
c = container.results[0];
|
|
console.log(c);
|
|
containerType = await getObjectInfo(c.container_type);
|
|
document.querySelector('#container_details').value = c.description + "\n" + c.named_id + ': ' + c.color + "\n" + containerType.description;
|
|
containerIsValid = true;
|
|
} else {
|
|
document.querySelector('#container_details').value = document.querySelector('#container_details').value + "\nERROR: No result\n";
|
|
console.log(response);
|
|
containerIsValid = false;
|
|
}
|
|
}
|
|
|
|
async function getAssetInfo(assetId) {
|
|
document.querySelector('#asset_id').value = assetId;
|
|
url = '/api/assets?named_id=' + assetId;
|
|
document.querySelector('#asset_details').value = 'Trying ' + url;
|
|
const response = await fetch(url);
|
|
const asset = await response.json();
|
|
if (asset.count >= 1) {
|
|
document.querySelector('#asset_details').value = asset.results[0].description;
|
|
assetIsValid = true;
|
|
} else {
|
|
document.querySelector('#asset_details').value = document.querySelector('#asset_details').value + "\nERROR: No result\n";
|
|
console.log(response);
|
|
assetIsValid = false;
|
|
}
|
|
}
|
|
|
|
function useScannedText(msg) {
|
|
document.querySelector('#chat-log').value += (msg + '\n');
|
|
if (msg.startsWith('C-')) {
|
|
getContainerInfo(msg);
|
|
} else if (msg.startsWith('A-')) {
|
|
getAssetInfo(msg);
|
|
} else {
|
|
assetId = 'A-' + msg;
|
|
document.querySelector('#asset_id').value = assetId;
|
|
getAssetInfo(assetId);
|
|
}
|
|
};
|
|
|
|
document.querySelector('#clear-chat-area').onclick = function(e) {
|
|
document.querySelector('#chat-log').value = "cleared\n";
|
|
}
|
|
|
|
document.querySelector('#book-in-button').onclick = function(e) {
|
|
if (!containerIsValid) {
|
|
msg = 'Cannot book-in as container is invalid';
|
|
console.log(msg);
|
|
document.querySelector('#chat-log').value += ('ERROR: ' + msg + '\n');
|
|
return;
|
|
}
|
|
if (!assetIsValid) {
|
|
msg = 'Cannot book-in as asset is invalid';
|
|
console.log(msg);
|
|
document.querySelector('#chat-log').value += ('ERROR: ' + msg + '\n');
|
|
return;
|
|
}
|
|
}
|
|
|
|
document.querySelector('#book-out-button').onclick = function(e) {
|
|
if (!containerIsValid) {
|
|
msg = 'Cannot book-out as container is invalid';
|
|
console.log(msg);
|
|
document.querySelector('#chat-log').value += ('ERROR: ' + msg + '\n');
|
|
return;
|
|
}
|
|
if (!assetIsValid) {
|
|
msg = 'Cannot book-out as asset is invalid';
|
|
console.log(msg);
|
|
document.querySelector('#chat-log').value += ('ERROR: ' + msg + '\n');
|
|
return;
|
|
}
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
{% endblock %}
|