first commit
This commit is contained in:
commit
a7a39efe49
|
@ -0,0 +1,32 @@
|
|||
extends: [eslint:recommended, google]
|
||||
parserOptions:
|
||||
ecmaVersion: 2021
|
||||
sourceType: "module"
|
||||
rules:
|
||||
require-jsdoc: 0
|
||||
no-undef: 0
|
||||
max-len: 0
|
||||
eqeqeq: 0
|
||||
operator-linebreak: 0
|
||||
radix: 0
|
||||
guard-for-in: 0
|
||||
camelcase: 0
|
||||
default-case: 0
|
||||
no-eq-null: 0
|
||||
no-console: 0
|
||||
no-warning-comments: 0
|
||||
no-empty: [error, allowEmptyCatch: true]
|
||||
complexity: 0
|
||||
max-depth: 0
|
||||
comma-dangle: 0
|
||||
bracketSpacing: 0
|
||||
space-infix-ops: 1
|
||||
no-invalid-this: 0
|
||||
space-before-function-paren: [error, never]
|
||||
prefer-const: 0
|
||||
curly: [error, multi-or-nest]
|
||||
indent: [error, 4]
|
||||
arrow-parens: [error, as-needed]
|
||||
no-multiple-empty-lines: ["error", { "max": 1, "maxEOF": 1 }]
|
||||
space-in-parens: ["error", "never"]
|
||||
arrow-spacing: ["error", { "before": true, "after": true }]
|
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
config.local.yml
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach",
|
||||
"restart": true,
|
||||
"timeout": 50000
|
||||
}, {
|
||||
"type": "node",
|
||||
"request": "attach",
|
||||
"name": "Attach by process ID",
|
||||
"processId": "${command:PickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
// Coloque su configuración en este archivo para sobrescribir la configuración predeterminada y de usuario.
|
||||
{
|
||||
// Carácter predeterminado de final de línea.
|
||||
"files.eol": "\n",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
FROM node
|
||||
WORKDIR /app
|
||||
COPY package.json ./
|
||||
RUN npm install
|
||||
COPY db db
|
||||
COPY src src
|
||||
COPY server.js ./
|
||||
CMD ["node", "server.js"]
|
|
@ -0,0 +1,65 @@
|
|||
#!/usr/bin/env groovy
|
||||
|
||||
pipeline {
|
||||
agent any
|
||||
options {
|
||||
disableConcurrentBuilds()
|
||||
}
|
||||
environment {
|
||||
PROJECT_NAME = 'vn-rfid'
|
||||
STACK_NAME = "${env.PROJECT_NAME}-${env.BRANCH_NAME}"
|
||||
}
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
script {
|
||||
switch (env.BRANCH_NAME) {
|
||||
case 'master':
|
||||
env.NODE_ENV = 'production'
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
setEnv()
|
||||
}
|
||||
}
|
||||
stage('Build') {
|
||||
when { anyOf {
|
||||
branch 'master'
|
||||
}}
|
||||
environment {
|
||||
CREDENTIALS = credentials('docker-registry')
|
||||
}
|
||||
steps {
|
||||
dockerBuild()
|
||||
}
|
||||
}
|
||||
stage('Deploy') {
|
||||
when { anyOf {
|
||||
branch 'master'
|
||||
}}
|
||||
environment {
|
||||
DOCKER_HOST = "${env.SWARM_HOST}"
|
||||
}
|
||||
steps {
|
||||
sh "docker stack deploy --with-registry-auth --compose-file docker-compose.yml ${env.STACK_NAME}"
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
script {
|
||||
if (!env.COMMITTER_EMAIL || currentBuild.currentResult == 'SUCCESS') return;
|
||||
try {
|
||||
mail(
|
||||
to: env.COMMITTER_EMAIL,
|
||||
subject: "Pipeline: ${env.JOB_NAME} (${env.BUILD_NUMBER}): ${currentBuild.currentResult}",
|
||||
body: "Check status at ${env.BUILD_URL}"
|
||||
)
|
||||
} catch (e) {
|
||||
echo e.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
## Getting Started // Installing
|
||||
|
||||
Pull from repository.
|
||||
|
||||
Run this commands on project root directory to install Node dependencies.
|
||||
```
|
||||
$ npm install
|
||||
```
|
||||
|
||||
Launch application in developer environment.
|
||||
```
|
||||
$ npm run start
|
||||
```
|
||||
|
||||
For test.
|
||||
```
|
||||
DELETE expedition in vn.expeditionScan
|
||||
```
|
|
@ -0,0 +1,99 @@
|
|||
const config = require('../config');
|
||||
const express = require('express');
|
||||
const router = express.Router(); // eslint-disable-line
|
||||
const got = require('got');
|
||||
const con = require('../db/connect');
|
||||
|
||||
// Obtenemos los parametros
|
||||
router.get('/:truckFk', async(req, res) => {
|
||||
const ip = config.ip;
|
||||
const truckFk = req.params.truckFk;
|
||||
let bufferTime = [];
|
||||
let bufferEpcHex = [];
|
||||
let interval;
|
||||
let jsonMessage;
|
||||
|
||||
console.log('--START BACKEND--');
|
||||
|
||||
const stream = await got.stream(`http://${ip}/api/v1/data/stream`);
|
||||
stream
|
||||
.on('data', value => {
|
||||
// value = '{"timestamp":"2022-07-27T11:57:39.226680176Z","tagInventoryEvent":{"epc":"qrsAAAAAAAAFdgQg","epcHex":"AABB00000000000005760420","pc":"MAA=","antennaPort":4,"antennaName":"4","peakRssiCdbm":-7600,"lastSeenTime":"2022-07-27T11:57:39.041444Z","phaseAngle":46.05}}'
|
||||
let buffer = value.toString();
|
||||
buffer = buffer.split('\n');
|
||||
for (let result of buffer) {
|
||||
if (result && /{.*:{.*:.*}}/.test(result)) {
|
||||
const jsonResult = JSON.parse(result);
|
||||
let epcHex = jsonResult?.tagInventoryEvent?.epcHex;
|
||||
|
||||
if (!epcHex) return;
|
||||
if (epcHex.search('AABB') == -1) return;
|
||||
|
||||
// console.log(epcHex)
|
||||
epcHex = epcHex.replace('AABB', '');
|
||||
const existEpcHex = element => element == epcHex;
|
||||
const bufferIndex = bufferEpcHex.findIndex(existEpcHex);
|
||||
|
||||
if (bufferIndex >= 0)
|
||||
return bufferTime[bufferIndex].count = bufferTime[bufferIndex].count + 1;
|
||||
|
||||
const newObject = {
|
||||
code: epcHex,
|
||||
created: jsonResult.timestamp,
|
||||
peakRssi: jsonResult.tagInventoryEvent.peakRssiCdbm,
|
||||
count: 1
|
||||
};
|
||||
bufferEpcHex.push(epcHex);
|
||||
bufferTime.push(newObject);
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
}
|
||||
interval = setInterval(insertDB, 5000, truckFk);
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('close', () => {
|
||||
console.log('CLOSE_STREAM');
|
||||
});
|
||||
|
||||
async function insertDB(truckFk) {
|
||||
clearInterval(interval);
|
||||
stream.destroy();
|
||||
|
||||
interval = null;
|
||||
console.log('--INSERT IN DB--');
|
||||
console.log(bufferEpcHex, bufferTime, truckFk);
|
||||
|
||||
const rfids = [];
|
||||
let response;
|
||||
for (let code of bufferEpcHex) {
|
||||
while (code.substring(0, 1) == 0)
|
||||
code = code.substring(1);
|
||||
|
||||
rfids.push(code);
|
||||
}
|
||||
|
||||
console.log('rfids', rfids.join(','));
|
||||
if (rfids.length)
|
||||
[response] = await con.query(`CALL vn.palletBuilding(?,?);`, [rfids.join(','), truckFk]);
|
||||
|
||||
console.log(response);
|
||||
console.log(response[0]);
|
||||
console.log(response[0][0]);
|
||||
console.log(response[0][0]?.palletFk);
|
||||
bufferTime = [];
|
||||
bufferEpcHex = [];
|
||||
const pallet = response[0][0]?.palletFk;
|
||||
if (pallet) {
|
||||
const print = await con.query(`CALL vn.expeditionPallet_printLabel(?);`, [pallet]);
|
||||
console.log('print', print);
|
||||
jsonMessage = {pallet: pallet, print: print};
|
||||
stream.destroy();
|
||||
return res.json(jsonMessage);
|
||||
}
|
||||
return res.json({error: 'ERROR_CREATING_PALLET'});
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -0,0 +1,124 @@
|
|||
const config = require('../config');
|
||||
const got = require('got');
|
||||
const con = require('../db/connect');
|
||||
|
||||
module.exports = async() => {
|
||||
const ip = config.ip;
|
||||
let bufferTime = [];
|
||||
let bufferEpcHex = [];
|
||||
let interval;
|
||||
let jsonMessage;
|
||||
|
||||
console.log('--START BACKEND--');
|
||||
|
||||
const stream = await got.stream(`http://${ip}/api/v1/data/stream`);
|
||||
stream
|
||||
.on('data', value => {
|
||||
// value = '{"timestamp":"2022-07-27T11:57:39.226680176Z","tagInventoryEvent":{"epc":"qrsAAAAAAAAFdgQg","epcHex":"AABB00000000000005760420","pc":"MAA=","antennaPort":4,"antennaName":"4","peakRssiCdbm":-7600,"lastSeenTime":"2022-07-27T11:57:39.041444Z","phaseAngle":46.05}}'
|
||||
let buffer = value.toString();
|
||||
buffer = buffer.split('\n');
|
||||
for (let result of buffer) {
|
||||
if (result && /{.*:{.*:.*}}/.test(result)) {
|
||||
const jsonResult = JSON.parse(result);
|
||||
let epcHex = jsonResult?.tagInventoryEvent?.epcHex;
|
||||
|
||||
if (!epcHex) return;
|
||||
if (epcHex.search('AABB') == -1) return;
|
||||
|
||||
// console.log(epcHex)
|
||||
epcHex = epcHex.replace('AABB', '');
|
||||
const existEpcHex = element => element == epcHex;
|
||||
const bufferIndex = bufferEpcHex.findIndex(existEpcHex);
|
||||
|
||||
if (bufferIndex >= 0)
|
||||
return bufferTime[bufferIndex].count = bufferTime[bufferIndex].count + 1;
|
||||
|
||||
const newObject = {
|
||||
code: epcHex,
|
||||
created: jsonResult.timestamp,
|
||||
peakRssi: jsonResult.tagInventoryEvent.peakRssiCdbm,
|
||||
count: 1
|
||||
};
|
||||
|
||||
bufferEpcHex.push(epcHex);
|
||||
bufferTime.push(newObject);
|
||||
insertLog(bufferTime);
|
||||
|
||||
if (interval) {
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
}
|
||||
interval = setInterval(insertDB, 10000);
|
||||
}
|
||||
}
|
||||
});
|
||||
/* .on("close", () => {
|
||||
console.log('CLOSE_STREAM')
|
||||
})*/
|
||||
|
||||
async function insertDB() {
|
||||
clearInterval(interval);
|
||||
|
||||
interval = null;
|
||||
// console.log('--INSERT IN DB--');
|
||||
// console.log(bufferEpcHex, bufferTime);
|
||||
|
||||
let rfids = [];
|
||||
let response;
|
||||
for (let code of bufferEpcHex) {
|
||||
while (code.substring(0, 1) == 0)
|
||||
code = code.substring(1);
|
||||
|
||||
rfids.push(parseInt(code));
|
||||
}
|
||||
|
||||
// console.log('rfids', rfids)
|
||||
rfids = await cleanDev(rfids);
|
||||
if (!rfids.length) return console.log({error: 'NOT_PARSED_RFIDS', rfids});
|
||||
|
||||
// response = await con.query(`CALL vn.pallet_build(JSON_ARRAY(?),?,@pallet);SELECT @pallet;`, params);
|
||||
response = await con.query(`CALL vn.pallet_build(JSON_ARRAY(?), ?, @pallet);SELECT @pallet;`, [rfids, 19294]);
|
||||
console.log(response);
|
||||
console.log(response[0][1][0]['@pallet']);
|
||||
|
||||
// console.log(response)
|
||||
// console.log(response[1]);
|
||||
bufferTime = [];
|
||||
bufferEpcHex = [];
|
||||
const pallet = response[0][1][0]['@pallet'];
|
||||
if (pallet) {
|
||||
console.log('CALL TO PRINT');
|
||||
const print = await con.query(`CALL vn.expeditionPallet_printLabel(?);`, [pallet]);
|
||||
// console.log('print', print)
|
||||
jsonMessage = {pallet: pallet, print: print};
|
||||
// stream.destroy();
|
||||
console.log(jsonMessage);
|
||||
} else
|
||||
console.log({error: 'ERROR_CREATING_PALLET', expeditions: rfids});
|
||||
}
|
||||
|
||||
async function insertLog() {
|
||||
const sql = `INSERT INTO lastRFID (code, antennaFk, isConsulted, isChoosed, antennaPort, peakRssi, seenCount)
|
||||
VALUES(?, 5, 1, 0, 1, ?, ?);`;
|
||||
|
||||
for (let rfid of bufferTime) {
|
||||
const response = await con.query(sql, [rfid.code, rfid.peakRssi, rfid.count]);
|
||||
// console.log('insertLog', response, [rfid.code, rfid.peakRssi, rfid.count])
|
||||
}
|
||||
}
|
||||
|
||||
async function cleanDev(ids) {
|
||||
if (config.env != 'dev') return ids;
|
||||
const sql = `SELECT id FROM vn.expedition WHERE id = ?`;
|
||||
|
||||
const idsCleaned = [];
|
||||
for (let id of ids) {
|
||||
const [response] = await con.query(sql, [id]);
|
||||
console.log('cleanDev', response);
|
||||
if (response.length > 0)
|
||||
idsCleaned.push(id);
|
||||
}
|
||||
|
||||
return idsCleaned;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,13 @@
|
|||
port: 1234
|
||||
ip: 1.2.3.4
|
||||
env: dev
|
||||
interval: 1000
|
||||
reconnectInterval: 5000
|
||||
db:
|
||||
host: host
|
||||
port: 3307
|
||||
database: srt
|
||||
user: user
|
||||
password: password
|
||||
multipleStatements: true
|
||||
insecureAuth: true
|
|
@ -0,0 +1,13 @@
|
|||
import mysql from 'mysql2/promise';
|
||||
import yml from 'require-yml';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
const {pathname: root} = new URL('../', import.meta.url);
|
||||
let conf = yml(path.join(root, 'config.yml'));
|
||||
const localConfFile = path.join(root, 'config.local.yml');
|
||||
if (fs.existsSync(localConfFile))
|
||||
conf = Object.assign({}, conf, yml(localConfFile));
|
||||
|
||||
export default mysql.createPool(conf.db);
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
version: '3.7'
|
||||
services:
|
||||
main:
|
||||
image: registry.verdnatura.es/vn-rfid:${BRANCH_NAME:?}
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
ports:
|
||||
- 8888
|
||||
configs:
|
||||
- source: config
|
||||
target: /app/config.local.yml
|
||||
deploy:
|
||||
placement:
|
||||
constraints:
|
||||
- node.role == worker
|
||||
configs:
|
||||
config:
|
||||
external: true
|
||||
name: vn-rfid_config
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "vn-rfid",
|
||||
"version": "1.0.0",
|
||||
"author": "Verdnatura Levante SL",
|
||||
"description": "rfid backend",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "nodemon ./server.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"eslint": "^7.22.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"express": "^4.17.1",
|
||||
"fs-extra": "^11.1.0",
|
||||
"got": "^11.8.2",
|
||||
"ip": "^1.1.5",
|
||||
"mysql2": "^2.3.3",
|
||||
"mysql2-promise": "^0.1.4",
|
||||
"nodemon": "^2.0.20",
|
||||
"require-yml": "^2.0.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
import stream from './src/stream.js';
|
||||
import yml from 'require-yml';
|
||||
import path from 'path';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
function main() {
|
||||
const {pathname: root} = new URL('./', import.meta.url);
|
||||
let conf = yml(path.join(root, 'config.yml'));
|
||||
const localConfFile = path.join(root, 'config.local.yml');
|
||||
if (fs.existsSync(localConfFile))
|
||||
conf = Object.assign({}, conf, yml(localConfFile));
|
||||
|
||||
try {
|
||||
stream(conf);
|
||||
} catch (e) {
|
||||
// Not working
|
||||
setTimeout(main(), conf.reconnectInterval);
|
||||
console.log('MAIN_ERROR', e);
|
||||
}
|
||||
}
|
||||
|
||||
main();
|
|
@ -0,0 +1,22 @@
|
|||
import con from '../db/connect.js';
|
||||
|
||||
export default async rfids => {
|
||||
let response;
|
||||
|
||||
if (!rfids.length) return console.log({error: 'NOT_PARSED_RFIDS', rfids});
|
||||
|
||||
const codes = new Set();
|
||||
for (let rfid of rfids)
|
||||
codes.add(parseInt(rfid.code));
|
||||
|
||||
console.log('CALL PALLET_BUILD', codes, ' TOTAL: ', codes.size);
|
||||
|
||||
response = await con.query(`CALL vn.expeditionPallet_build(JSON_ARRAY(?), ?, @pallet);SELECT @pallet;`, [Array.from(codes), 19294]);
|
||||
|
||||
const pallet = response[0][1][0]['@pallet'];
|
||||
if (pallet) {
|
||||
console.log('PRINTING', pallet);
|
||||
await con.query(`CALL vn.expeditionPallet_printLabel(?);`, [pallet]);
|
||||
} else
|
||||
console.log({error: 'ERROR_CREATING_PALLET', expeditions: rfids});
|
||||
};
|
|
@ -0,0 +1,29 @@
|
|||
export default async data => {
|
||||
data = data.toString();
|
||||
const crudeRfids = data.split('\n');
|
||||
|
||||
const rfidsParsed = [];
|
||||
for (let crudeRfid of crudeRfids) {
|
||||
if (crudeRfid && /{.*:{.*:.*}}/.test(crudeRfid)) {
|
||||
const jsonResult = JSON.parse(crudeRfid);
|
||||
let epcHex = jsonResult?.tagInventoryEvent?.epcHex;
|
||||
|
||||
if (!epcHex) return;
|
||||
if (epcHex.search('AABB') == -1) continue;
|
||||
|
||||
epcHex = epcHex.replace('AABB', '');
|
||||
epcHex = epcHex.substring(0, 1) == 0 ? epcHex.substring(1) : epcHex;
|
||||
const rfidParsed = {
|
||||
code: parseInt(epcHex),
|
||||
created: jsonResult.timestamp,
|
||||
peakRssi: jsonResult.tagInventoryEvent.peakRssiCdbm,
|
||||
count: 1,
|
||||
antenna: jsonResult.tagInventoryEvent.antennaPort
|
||||
};
|
||||
|
||||
rfidsParsed.push(rfidParsed);
|
||||
}
|
||||
}
|
||||
|
||||
return rfidsParsed;
|
||||
};
|
|
@ -0,0 +1,63 @@
|
|||
import got from 'got';
|
||||
import rfidParser from './rfidParser.js';
|
||||
import newPallet from './newPallet.js';
|
||||
|
||||
let interval;
|
||||
|
||||
export default async conf => {
|
||||
let rfidbuffer = [];
|
||||
let rfidbufferSet = [new Set(), new Set(), new Set(), new Set()];
|
||||
|
||||
const stream = got.stream(`http://${conf.ip}/api/v1/data/stream`);
|
||||
|
||||
stream
|
||||
.on('data', async value => {
|
||||
const parsed = await rfidParser(value);
|
||||
|
||||
if (parsed)
|
||||
rfidbuffer = rfidbuffer.concat(parsed);
|
||||
|
||||
debug();
|
||||
|
||||
if (rfidbuffer && rfidbuffer.length && parsed && parsed.length) {
|
||||
clearInterval(interval);
|
||||
interval = null;
|
||||
interval = setInterval(createPallet, conf.interval);
|
||||
}
|
||||
})
|
||||
.on('error', e => {
|
||||
throw new Error('ERROR_STREAM', e);
|
||||
});
|
||||
|
||||
function createPallet() {
|
||||
clearInterval(interval); // try remove
|
||||
if (!rfidbuffer.length) return;
|
||||
newPallet(rfidbuffer);
|
||||
rfidbuffer = [];
|
||||
rfidbufferSet = [new Set(), new Set(), new Set(), new Set()];
|
||||
}
|
||||
|
||||
function debug() {
|
||||
if (conf.env != 'dev') return;
|
||||
let totalBuffer = rfidbuffer.map(rfid => rfid.code);
|
||||
let totalBufferSet = new Set(totalBuffer);
|
||||
console.log('TOTAL BUFFER: ', totalBufferSet.size);
|
||||
|
||||
const totalRead = [0, 0, 0, 0];
|
||||
for (let buffer of rfidbuffer)
|
||||
totalRead[buffer.antenna - 1]++;
|
||||
console.log('TOTAL READ ANTENNA:', totalRead);
|
||||
|
||||
for (let buffer of parsed)
|
||||
rfidbufferSet[buffer.antenna - 1].add(buffer.code);
|
||||
console.log('UNIQUE READ ANTENNA:', rfidbufferSet[0].size, rfidbufferSet[1].size, rfidbufferSet[2].size, rfidbufferSet[3].size);
|
||||
for (const [index, set] of rfidbufferSet.entries()) {
|
||||
if (((set.size * 100) / totalBufferSet.size) < 25)
|
||||
console.log('[WARNING_ANTENNA]: ', index, ' ONLY ', set.size);
|
||||
}
|
||||
|
||||
console.log('----------------------------------------------------------------');
|
||||
}
|
||||
};
|
||||
|
||||
50;
|
Loading…
Reference in New Issue