Skip to content
Snippets Groups Projects
Commit de310083 authored by Antoine Rochebois's avatar Antoine Rochebois
Browse files

custom WebUSB classes and connect button

parent 0abeab82
No related branches found
No related tags found
No related merge requests found
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
</div> </div>
<div id="navMenu" class="navbar-menu" :class="{ 'is-active': showNav }"> <div id="navMenu" class="navbar-menu" :class="{ 'is-active': showNav }">
<div class="navbar-start"> <div class="navbar-start">
<a v-if="$store.state.isLoggedIn" class="navbar-item"
><router-link to="/results"
><i class="fas fa-flag-checkered" /> Enregistrer des résultats</router-link
></a
>
<a class="navbar-item" <a class="navbar-item"
><router-link to="/encoder" ><router-link to="/encoder"
><i class="fas fa-code" /> Encodeur NFC</router-link ><i class="fas fa-code" /> Encodeur NFC</router-link
...@@ -38,7 +43,9 @@ ...@@ -38,7 +43,9 @@
> >
</div> </div>
<div class="navbar-end"> <div class="navbar-end">
<div class="buttons has-addons"> <div class="buttons has-addons">
<a class="navbar-item button is-info" @click="connectUsb()"><span><i class="fab fa-usb"></i> Connexion lecteur NFC</span></a>
<a v-if="!$store.state.isLoggedIn" class="navbar-item button" <a v-if="!$store.state.isLoggedIn" class="navbar-item button"
><router-link to="/register" ><router-link to="/register"
><span ><span
...@@ -77,7 +84,8 @@ ...@@ -77,7 +84,8 @@
<script> <script>
import PageFooter from "./components/PageFooter.vue"; import PageFooter from "./components/PageFooter.vue";
import UsbNfcReader from "./usbNfcReader.js"
var usbNfcReader = new UsbNfcReader();
export default { export default {
name: "app", name: "app",
data() { data() {
...@@ -92,6 +100,9 @@ export default { ...@@ -92,6 +100,9 @@ export default {
console.log(response); console.log(response);
this.$store.commit("logout"); this.$store.commit("logout");
}); });
},
connectUsb() {
usbNfcReader.selectAndConnect()
} }
}, },
components: { components: {
......
<template>
<div class="content">
<article v-if="this.team.name.length > 0" class="message is-info">
<div class="message-header">
Résultats de l'équipe {{ team.name }} ({{ memberCount }} membres)
</div>
<div class="message-body">
<div>
<p class="is-size-4"><strong>Membres de l'équipe :</strong></p>
<ul>
<li v-for="member in team.members" :key="member">{{ member }}</li>
</ul>
</div>
<div>
<p v-if="team.donePuzzles.length > 0" class="is-size-4">
<strong>Puzzles effectués :</strong>
</p>
<div v-for="puzzle in team.donePuzzles" :key="puzzle.name">
<div class="level" v-if="puzzle.score">
<div class="level-item level-left">
<p>
<strong>{{ puzzle.name }}</strong> ({{ puzzle.room }}) :
</p>
</div>
<div class="level-item level-right">
<progress
class="progress is-small"
:value="puzzle.score"
:max="puzzle.maxScore"
></progress>
</div>
<div class="level-item level-right">
<p>{{ puzzle.score }}/{{ puzzle.maxScore }}</p>
</div>
</div>
<div v-else class="level ">
<div class="level-item level-left">
<p>
<strong>{{ puzzle.name }}</strong> ({{ puzzle.room }}) :
</p>
</div>
<div class="level-item level-right">
<span v-if="puzzle.validated" class="icon has-text-success">
<i class="fas fa-check-circle"></i>
</span>
<span v-else class="icon has-text-danger">
<i class="fas fa-times-circle"></i>
</span>
</div>
</div>
</div>
</div>
</div>
</article>
<article v-else>
<p>Merci de scanner une carte d'équipe pour afficher et enregistrer des résultats</p>
<button class="button is-primary" @click="showPairingModal = !showPairingModal"><i class="fas fa-download"></i> Scanner la carte de l'équipe !</button>
</article>
<div class="modal" :class="{ 'is-active': showPairingModal }">
<div class="modal-background"></div>
<div class="modal-content">
<div class="message">
<div class="message-header">
Lecture d'une carte NFC d'équipe
</div>
<div class="message-body">
Veuillez scanner une carte sur le lecteur pour charger ses résultats
équipe.
</div>
</div>
</div>
<button
class="modal-close is-large"
@click="showPairingModal = false"
></button>
</div>
</div>
</template>
<script>
export default {
name: "ResultDisplay",
data() {
return {
showPairingModal: false,
team : { name: "", members: [], donePuzzles : [] }
};
},
computed: {
memberCount: function() {
return this.team.members.length;
}
},
methods: {
}
};
</script>
<style scoped></style>
...@@ -6,12 +6,14 @@ import App from "./App.vue"; ...@@ -6,12 +6,14 @@ import App from "./App.vue";
import VueAxios from "vue-axios"; import VueAxios from "vue-axios";
import axios from "axios"; import axios from "axios";
import HomeComponent from "./components/HomeComponent.vue"; import HomeComponent from "./components/HomeComponent.vue";
import SchoolManager from "./components/SchoolManager.vue"; import SchoolManager from "./components/SchoolManager.vue";
import MentionsLegales from "./components/MentionsLegales.vue"; import MentionsLegales from "./components/MentionsLegales.vue";
import Login from "./components/Login.vue"; import Login from "./components/Login.vue";
import Register from "./components/Register.vue"; import Register from "./components/Register.vue";
import Encoder from "./components/Encoder.vue"; import Encoder from "./components/Encoder.vue";
import ResultsDisplay from "./components/ResultsDisplay.vue";
require("@/assets/main.scss"); require("@/assets/main.scss");
import "@fortawesome/fontawesome-free/css/all.css"; import "@fortawesome/fontawesome-free/css/all.css";
import "@fortawesome/fontawesome-free/js/all.js"; import "@fortawesome/fontawesome-free/js/all.js";
...@@ -28,6 +30,11 @@ const routes = [ ...@@ -28,6 +30,11 @@ const routes = [
path: "/", path: "/",
component: HomeComponent component: HomeComponent
}, },
{
name: "resultsDisplay",
path: "/results",
component: ResultsDisplay
},
{ {
name: "encoder", name: "encoder",
path: "/encoder", path: "/encoder",
......
var serial = {};
(function() {
'use strict';
serial.getPorts = function() {
return navigator.usb.getDevices().then(devices => {
return devices.map(device => new serial.Port(device));
});
};
serial.requestPort = function() {
const filters = [
{ 'vendorId': 0x2341, 'productId': 0x8036 }, // Arduino Leonardo
{ 'vendorId': 0x2341, 'productId': 0x8037 }, // Arduino Micro
{ 'vendorId': 0x2341, 'productId': 0x804d }, // Arduino/Genuino Zero
{ 'vendorId': 0x2341, 'productId': 0x804e }, // Arduino/Genuino MKR1000
{ 'vendorId': 0x2341, 'productId': 0x804f }, // Arduino MKRZERO
{ 'vendorId': 0x2341, 'productId': 0x8050 }, // Arduino MKR FOX 1200
{ 'vendorId': 0x2341, 'productId': 0x8052 }, // Arduino MKR GSM 1400
{ 'vendorId': 0x2341, 'productId': 0x8053 }, // Arduino MKR WAN 1300
{ 'vendorId': 0x2341, 'productId': 0x8054 }, // Arduino MKR WiFi 1010
{ 'vendorId': 0x2341, 'productId': 0x8055 }, // Arduino MKR NB 1500
{ 'vendorId': 0x2341, 'productId': 0x8056 }, // Arduino MKR Vidor 4000
{ 'vendorId': 0x2341, 'productId': 0x8057 }, // Arduino NANO 33 IoT
{ 'vendorId': 0x239A }, // Adafruit Boards!
];
return navigator.usb.requestDevice({ 'filters': filters }).then(
device => new serial.Port(device)
);
}
serial.Port = function(device) {
this.device_ = device;
this.interfaceNumber_ = 2; // original interface number of WebUSB Arduino demo
this.endpointIn_ = 5; // original in endpoint ID of WebUSB Arduino demo
this.endpointOut_ = 4; // original out endpoint ID of WebUSB Arduino demo
};
serial.Port.prototype.connect = function() {
let readLoop = () => {
this.device_.transferIn(this.endpointIn_, 64).then(result => {
this.onReceive(result.data);
readLoop();
}, error => {
this.onReceiveError(error);
});
};
return this.device_.open()
.then(() => {
if (this.device_.configuration === null) {
return this.device_.selectConfiguration(1);
}
})
.then(() => {
var configurationInterfaces = this.device_.configuration.interfaces;
configurationInterfaces.forEach(element => {
element.alternates.forEach(elementalt => {
if (elementalt.interfaceClass==0xff) {
this.interfaceNumber_ = element.interfaceNumber;
elementalt.endpoints.forEach(elementendpoint => {
if (elementendpoint.direction == "out") {
this.endpointOut_ = elementendpoint.endpointNumber;
}
if (elementendpoint.direction=="in") {
this.endpointIn_ =elementendpoint.endpointNumber;
}
})
}
})
})
})
.then(() => this.device_.claimInterface(this.interfaceNumber_))
.then(() => this.device_.selectAlternateInterface(this.interfaceNumber_, 0))
.then(() => this.device_.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request': 0x22,
'value': 0x01,
'index': this.interfaceNumber_}))
.then(() => {
readLoop();
});
};
serial.Port.prototype.disconnect = function() {
return this.device_.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request': 0x22,
'value': 0x00,
'index': this.interfaceNumber_})
.then(() => this.device_.close());
};
serial.Port.prototype.send = function(data) {
return this.device_.transferOut(this.endpointOut_, data);
};
})();
export default serial;
import Serial from "./serial.js"
export default class UsbNfcReader {
constructor() {
this.textEncoder = new TextEncoder();
//Tentative de connexion/reconnexion automatique
Serial.getPorts().then(ports => {
if (ports.length == 0) {
console.log('No devices found.');
} else {
this.port = ports[0];
console.log("Port choisi :", this.port);
this.connect();
}
});
}
selectAndConnect() {
Serial.requestPort().then(selectedPort => {
this.port = selectedPort;
this.connect();
}).catch(error => {
console.log('Connection error: ' + error);
});
}
disconnect() {
this.port.disconnect();
this.port = null;
}
connect() {
console.log('Connecting to ' + this.port.device_.productName + '...');
this.port.connect().then(() => {
console.log(this.port, 'Connected.');
//Important : callback de réception
this.port.onReceive = data => {
let textDecoder = new TextDecoder();
this.receivedMsg = textDecoder.decode(data);
console.log("Reçu :" + this.receivedMsg);
}
this.port.onReceiveError = error => {
console.log('Receive error: ' + error);
};
}, error => {
console.log('Connection error: ' + error);
});
}
//Envoie ce string à l'Arduino
sendString(str) {
if (this.port !== undefined) {
this.port.send(this.textEncoder.encode(str)).catch(error => {
console.log('Send error: ' + error);
});
}
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment