lcd support, potential support for card renewal

master
Henry Jameson 2 years ago
parent e4a98a9de6
commit daedc49e6b
  1. 84
      index.js
  2. 2
      package.json
  3. 62
      statuslogger.js
  4. 30
      yarn.lock

@ -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()

@ -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"
}
}

@ -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++]
}
}
}

@ -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"

Loading…
Cancel
Save