From daedc49e6b885293ea926c2eff1de1037831c016 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 26 Aug 2022 01:48:09 +0300 Subject: [PATCH] lcd support, potential support for card renewal --- index.js | 84 ++++++++++++++++++++++++++++++++----------------- package.json | 2 ++ statuslogger.js | 62 ++++++++++++++++++++++++++++++++++++ yarn.lock | 30 +++++++++++++++++- 4 files changed, 148 insertions(+), 30 deletions(-) create mode 100644 statuslogger.js diff --git a/index.js b/index.js index e9faa22..a38067e 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,13 @@ import { NFC } from 'nfc-pcsc' import fetch from 'node-fetch' import fs from 'fs' +import { Feedback } from './statuslogger.js' const CARDS_LOCATION = '/home/snufkin/Repos/apps/YACards/' +const logger = Feedback() +logger.initLCD() -console.log('[ ][INF][EABU]: Starting up (if this hangs check if pcscd is running)') +logger.info('[EABU]: Starting up (if this hangs check if pcscd is running)') const nfc = new NFC() const status = { card: null, @@ -13,87 +16,101 @@ const status = { guestPlay: false, readyCard: false, countdown: 0, - newCard: false + newCard: false, + renewPossible: false, } -console.log('[ ][INF][EABU]: NFC Initialized') +logger.info('[EABU]: NFC Initialized') nfc.on('error', err => { - console.error('[!][ERR][PCSC]:', err); + logger.error('[PCSC]:', err); }); nfc.on('reader', reader => { - // reader.aid = 'F222222222'; reader.on('card', card => { - console.log(`[C][INF][PCSC] Card ${card.uid} scanned`) + logger.info(`[PCSC] Card ${card.uid} scanned`) + logger.lcd3('Card:' + card.uid.slice(0, 20 - 5)) if (status.card === null && !status.guestPlay) { status.card = card.uid status.confirmed = false status.countdown = 5 status.newCard = !fs.existsSync(CARDS_LOCATION + card.uid + '.track_0') - console.log(`[C][INF][YACE] Telling YACE to insert ${card.uid}`) + logger.info(`[YACE] Telling YACE to insert ${card.uid}`) if (status.newCard) { - console.log(`[C][INF][EABU] New card!`) + logger.info(`[EABU] New card!`) + logger.lcd2(' New card! ') status.newCardRegistration = true - status.countdown = 300 // seconds + status.countdown = 600 // seconds fetch('http://localhost:8082/api/v1/loadedCard?cardname=' + card.uid, { method: 'POST' }) } else { - console.log(`[C][INF][EABU] Existing card!`) + logger.info(`[EABU] Existing card!`) + logger.lcd2(' Welcome back! ') if (status.readyCard) { - console.log(`[C][INF][EABU] Inserting...`) + logger.info(`[EABU] Inserting...`) fetch('http://localhost:8082/api/v1/insertedCard?cardname=' + card.uid, { method: 'POST' }) } else { - console.log(`[C][INF][EABU] Not inserting as game isn't ready for it...`) + logger.info(`[EABU] Not inserting as game isn't ready for it...`) + logger.lcd2('Scan card only when ') + logger.lcd3('game asks for it !! ') status.card = null status.confirmed = false status.countdown = 0 } } } else { - console.log(`[C][INF][EABU] Ignoring as we already have a card or GUEST is playing...`) + logger.info(`[EABU] Ignoring as we already have a card or GUEST is playing...`) + logger.lcd2('Card ignored: ') + logger.lcd3('Guest is playing rn!') } }) reader.on('error', err => { - console.error('[!][ERR][PCSC] ', err); + logger.error('[PCSC] ', err); }); }) const pollYACE = () => { - // console.debug('[ ][DEB][EABU] STATUS ' + JSON.stringify(status)) if (status.card !== null) { - // fetch('http://localhost:8082/api/v1/insertedCard') - // .then(res => res.json()) - // .then(bool => console.log('[ ][INF][YACE] Emulator card inserted: ' + bool.inserted)) fetch('http://localhost:8082/api/v1/hasCard') .then(res => res.json()) .then(bool => { - // console.debug('[ ][DEB][YACE] Emulator card present: ' + bool) if (status.countdown > 0) { // counting down trying to confirm insertion status.countdown-- status.confirmed = bool + logger.lcd1('Countdown: ' + ('' + status.countdown).padStart(9, ' ')) if (bool) status.countdown = 0 setTimeout(pollYACE, 1000) } else if (!status.confirmed) { // couldn't confirm insertion status.card = null status.newCard = false - console.error('[!][ERR][YACE] Could not confirm card presence with emulator!') - console.error('[!][INF][YACE] Telling YACE to load dummy just in case') + logger.lcd1('FAILED??????????????') + logger.error('[YACE] Could not confirm card presence with emulator!') + logger.error('[YACE] Telling YACE to load dummy just in case') fetch('http://localhost:8082/api/v1/loadedCard?cardname=dummy', { method: 'POST' }) setTimeout(pollYACE, 1000) } else { // insertion confirmed! waiting for ejection - if (!bool) { + logger.lcd1('Card inserted, glhf!') + if (!bool && !status.renewPossible) { + status.renewPossible = true + status.countdown = 100 + } else if (!bool && status.renewPossible) { + logger.lcd1('Thanks for playing!!') status.card = null status.newCard = false - console.error('[!][INF][YACE] Telling YACE to load dummy') + status.renewPossible = false + logger.info('[YACE] Telling YACE to load dummy') fetch('http://localhost:8082/api/v1/loadedCard?cardname=dummy', { method: 'POST' }) + } else { + logger.lcd1(' Card renewed! ') + status.newCard = false + status.renewPossible = false } setTimeout(pollYACE, 500) } }) .catch(err => { - console.error('[!][ERR][EABU] Failure polling YACE') + logger.error('[EABU] Failure polling YACE', err) setTimeout(pollYACE, 2000) }) } else { @@ -101,16 +118,22 @@ const pollYACE = () => { .then(res => res.json()) .then(bool => { if (status.guestPlay) { - console.debug('[ ][DEB][YACE] Emulator GUEST card present: ' + bool) + logger.info('[YACE] Emulator GUEST card present: ' + bool) } if (bool) { status.guestPlay = true + logger.lcd1(' Guest play engaged ') } if (status.guestPlay && !bool) { status.guestPlay = false + logger.lcd1(' Guest play ended ') } setTimeout(pollYACE, 200) }) + .catch(err => { + logger.error('[EABU] Failure polling YACE') + setTimeout(pollYACE, 2000) + }) } } @@ -119,13 +142,16 @@ const pollYACE2 = () => { .then(res => res.json()) .then(bool => { status.readyCard = bool + if (status.readyCard) { + logger.lcd1('!SCAN YOUR CARD NOW!') + } else { + logger.lcd1('Waiting for game... ') + } setTimeout(pollYACE2, 500) }) .catch(err => { - console.error('[!][ERR][EABU] Failure polling YACE (loop2)') - setTimeout(pollYACE2, 2000) - }) -} + logger.error('[EABU] Failure polling YACE (loop2)') + setTimeout(pollYACE2, 2000)})} pollYACE() pollYACE2() diff --git a/package.json b/package.json index f476a82..10542cb 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,10 @@ { "type": "module", "dependencies": { + "chalk": "^5.0.1", "nfc-pcsc": "^0.8.1", "node-fetch": "^3.2.9", + "raspberrypi-liquid-crystal": "^1.18.0", "yarn": "^1.22.18" } } diff --git a/statuslogger.js b/statuslogger.js new file mode 100644 index 0000000..10e7f7e --- /dev/null +++ b/statuslogger.js @@ -0,0 +1,62 @@ +import chalk from 'chalk' +import LCD from 'raspberrypi-liquid-crystal' +let lcd + +const err = chalk.bold.redBright +const inf = chalk.blueBright +const wrn = chalk.yellowBright + +export const Feedback = () => { + const spinner = ['/', '-', '\\', '|'] + const status = { + hasLCD: false, + spinnerIndex: 0, + spinner: spinner[0] + } + return { + warn(string) { + console.warn(wrn('[!]') + ' ' + string) + }, + info(string) { + console.info(inf('[ ]') + ' ' + string) + }, + error(string) { + console.error(err('[!]') + ' ' + string) + }, + lcd0(string) { + lcd.printLineSync(0, string) + }, + lcd1(string) { + lcd.printLineSync(1, string) + }, + lcd2(string) { + lcd.printLineSync(2, string) + }, + lcd3(string) { + lcd.printLineSync(3, string) + }, + initLCD() { + this.info('Initializing LCD...') + let lcd = new LCD( 1, 0x27, 16, 2 ); + return lcd + .begin() + .then(() => { + status.hasLCD = tru + this.info('LCD Initialized!') + lcd.clearSync() + lcd.printLineSync(0, 'Wangan Midnight ') + lcd.printLineSync(1, ' Maximum Tune 3DX+') + lcd.printLineSync(2, ' IC card support ') + lcd.printLineSync(3, ' by HJ (and GXTX)') + }) + .catch((e) => { + status.hasLCD = false + this.warn('Error initializing LCD: ', e) + }) + }, + advanceSpinner() { + if (status.spinnerIndex >= spinner.length) status.spinnerIndex = 0 + status.spinner = spinner[status.spinnerIndex++] + } + } +} diff --git a/yarn.lock b/yarn.lock index 24b3352..21d3371 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,6 +17,11 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" +chalk@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" + integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== + data-uri-to-buffer@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" @@ -42,7 +47,15 @@ formdata-polyfill@^4.0.10: dependencies: fetch-blob "^3.1.2" -nan@^2.14.0: +i2c-bus@^5.1.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/i2c-bus/-/i2c-bus-5.2.2.tgz#0c727f5e99443c5734b4f0e05b45748ba85008fa" + integrity sha512-b2y/et08rqggEjqod6QxV0Ng+RlSkZXsdE+E1aZEQBahepZ9uFD9XfA77Y8O9SgyhwfGEn+CNxsw0gvXW1/m4g== + dependencies: + bindings "^1.5.0" + nan "^2.14.2" + +nan@^2.14.0, nan@^2.14.1, nan@^2.14.2: version "2.16.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== @@ -68,6 +81,21 @@ node-fetch@^3.2.9: fetch-blob "^3.1.4" formdata-polyfill "^4.0.10" +raspberrypi-liquid-crystal@^1.18.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/raspberrypi-liquid-crystal/-/raspberrypi-liquid-crystal-1.18.0.tgz#95a6316502515881ae102226bae0dcab33b722de" + integrity sha512-NXGYLzgZkcnH11F6ieALINjU2fvHb0wMKdmEnyjHCwC0FTxW+gCaKSAPN2iUv2u4jbTBJ4cY8pDaMIBfnJ1dzA== + dependencies: + i2c-bus "^5.1.0" + sleep "^6.3.0" + +sleep@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/sleep/-/sleep-6.3.0.tgz#c524e0e6d8d2e45d3f14e0ba5650fbe45f2ae876" + integrity sha512-+WgYl951qdUlb1iS97UvQ01pkauoBK9ML9I/CMPg41v0Ze4EyMlTgFTDDo32iYj98IYqxIjDMRd+L71lawFfpQ== + dependencies: + nan "^2.14.1" + web-streams-polyfill@^3.0.3: version "3.2.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6"