update status
This commit is contained in:
parent
2c89f32c8d
commit
1941ab0c52
|
@ -1,31 +1,33 @@
|
||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events') // eslint-disable-line
|
||||||
const escpos = require('escpos')
|
const escpos = require('escpos')
|
||||||
const config = require('./config.json')
|
// const config = require('./config.json')
|
||||||
const fs = require('fs')
|
const fs = require('fs')
|
||||||
const iconv = require('iconv-lite')
|
const iconv = require('iconv-lite')
|
||||||
|
|
||||||
class PrinterDevice {
|
class PrinterDevice {
|
||||||
constructor() {
|
constructor () {
|
||||||
|
this._serial = ''
|
||||||
|
this._feed = 8
|
||||||
this._isOpen = false
|
this._isOpen = false
|
||||||
this._device = null
|
this._device = null
|
||||||
this._printer = null
|
this._printer = null
|
||||||
this._type = null // type = serial or console
|
this._type = null // type = serial or console
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeStr(str){
|
encodeStr (str) {
|
||||||
if(!str || typeof str != 'string') return false
|
if (!str || typeof str !== 'string') return false
|
||||||
return iconv.encode(str, 'big5')
|
return iconv.encode(str, 'big5')
|
||||||
}
|
}
|
||||||
|
|
||||||
async connect() {
|
async connect () {
|
||||||
let chkSerial = await new Promise((resolve, reject) => {
|
let chkSerial = await new Promise((resolve, reject) => {
|
||||||
fs.access(config.printer.serial, err => {
|
fs.access(this._serial, err => {
|
||||||
if (err) return resolve(false)
|
if (err) return resolve(false)
|
||||||
return resolve(true)
|
return resolve(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
if (chkSerial) {
|
if (chkSerial) {
|
||||||
this._device = new escpos.Serial(config.printer.serial)
|
this._device = new escpos.Serial(this._serial)
|
||||||
this._type = 'serial'
|
this._type = 'serial'
|
||||||
} else {
|
} else {
|
||||||
this._device = new escpos.Console()
|
this._device = new escpos.Console()
|
||||||
|
@ -35,8 +37,8 @@ class PrinterDevice {
|
||||||
this.openSerial()
|
this.openSerial()
|
||||||
}
|
}
|
||||||
|
|
||||||
async openSerial() {
|
async openSerial () {
|
||||||
if (!this._device || this._type != 'serial') return
|
if (!this._device || this._type !== 'serial') return
|
||||||
this._isOpen = await new Promise((resolve, reject) => {
|
this._isOpen = await new Promise((resolve, reject) => {
|
||||||
this._device.open(err => {
|
this._device.open(err => {
|
||||||
if (err) return resolve(false)
|
if (err) return resolve(false)
|
||||||
|
@ -45,7 +47,7 @@ class PrinterDevice {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async printerString(str) {
|
async printerString (str) {
|
||||||
if (!this._isOpen || !this._printer) return false
|
if (!this._isOpen || !this._printer) return false
|
||||||
|
|
||||||
this._printer.font('a')
|
this._printer.font('a')
|
||||||
|
@ -66,8 +68,8 @@ class PrinterDevice {
|
||||||
case 's':
|
case 's':
|
||||||
let size = tmp.substring(2)
|
let size = tmp.substring(2)
|
||||||
let sarr = size.trim().split(',')
|
let sarr = size.trim().split(',')
|
||||||
if (sarr.length != 2) break
|
if (sarr.length !== 2) break
|
||||||
if(!isFinite(sarr[0]) || !isFinite(sarr[1])) break
|
if (!isFinite(sarr[0]) || !isFinite(sarr[1])) break
|
||||||
sarr = sarr.map(t => Math.floor(t))
|
sarr = sarr.map(t => Math.floor(t))
|
||||||
this._printer.size(sarr[0], sarr[1])
|
this._printer.size(sarr[0], sarr[1])
|
||||||
break
|
break
|
||||||
|
@ -77,26 +79,50 @@ class PrinterDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._printer.cut(true, config.printer.cutFeed || 4)
|
this._printer.cut(true, this._feed || 4)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
async close() {
|
async printTestPage () {
|
||||||
|
await this.connect()
|
||||||
|
if (!this._isOpen) return false
|
||||||
|
this._printer.align('ct')
|
||||||
|
this._printer.size(1, 1)
|
||||||
|
this._printer.text('Print Test Page')
|
||||||
|
this._printer.align('lt')
|
||||||
|
this._printer.size(1, 1)
|
||||||
|
this._printer.text('Test Page Content')
|
||||||
|
await this.close()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async close () {
|
||||||
if (!this._device) return
|
if (!this._device) return
|
||||||
if (this._type == 'serial') {
|
if (this._type === 'serial') {
|
||||||
let self = this
|
let self = this
|
||||||
await new Promise((resolve, reject) => {
|
await new Promise((resolve, reject) => {
|
||||||
self._printer.close(() => {
|
self._printer.close(() => {
|
||||||
|
self._printer = null
|
||||||
|
self._isOpen = false
|
||||||
resolve(1)
|
resolve(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get isOpen() {
|
get isOpen () {
|
||||||
return this._isOpen ? true : false
|
return !!this._isOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
set serial (str) {
|
||||||
|
this._serial = str
|
||||||
|
}
|
||||||
|
|
||||||
|
set feed (str) {
|
||||||
|
if (!isFinite(str)) return
|
||||||
|
this._feed = Math.floor(parseInt(str))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new PrinterDevice()
|
module.exports = new PrinterDevice()
|
||||||
|
|
2
app.js
2
app.js
|
@ -1,2 +1,2 @@
|
||||||
require('top-level-await')
|
require('top-level-await')
|
||||||
require('./server')
|
require('./server')
|
||||||
|
|
|
@ -12,7 +12,7 @@ const notifyDesciptor = new bleno.Descriptor({
|
||||||
})
|
})
|
||||||
|
|
||||||
class DataCharacteristic extends bleno.Characteristic {
|
class DataCharacteristic extends bleno.Characteristic {
|
||||||
constructor() {
|
constructor () {
|
||||||
super({
|
super({
|
||||||
uuid: config.uuid.service.func.data,
|
uuid: config.uuid.service.func.data,
|
||||||
properties: ['write', 'writeWithoutResponse', 'notify'],
|
properties: ['write', 'writeWithoutResponse', 'notify'],
|
||||||
|
@ -23,15 +23,15 @@ class DataCharacteristic extends bleno.Characteristic {
|
||||||
this._notifyFunc = null
|
this._notifyFunc = null
|
||||||
}
|
}
|
||||||
|
|
||||||
onWriteRequest(data, offset, withoutResponse, callback) {
|
onWriteRequest (data, offset, withoutResponse, callback) {
|
||||||
console.log(`offset :: ${offset} , withoutRes :: ${withoutResponse}`)
|
console.log(`offset :: ${offset} , withoutRes :: ${withoutResponse}`)
|
||||||
console.log(`get data`, data)
|
console.log(`get data`, data)
|
||||||
|
|
||||||
if (data.length == 1 && data[0] == 0x00) {
|
if (data.length === 1 && data[0] === 0x00) {
|
||||||
tmp = []
|
tmp = []
|
||||||
idx = 0
|
idx = 0
|
||||||
failFlag = false
|
failFlag = false
|
||||||
} else if (data.length == 1 && data[0] == 0xff) {
|
} else if (data.length === 1 && data[0] === 0xff) {
|
||||||
console.log(Buffer.from(tmp).toString())
|
console.log(Buffer.from(tmp).toString())
|
||||||
if (!failFlag) {
|
if (!failFlag) {
|
||||||
localEvent.emit('print', Buffer.from(tmp).toString())
|
localEvent.emit('print', Buffer.from(tmp).toString())
|
||||||
|
@ -53,17 +53,17 @@ class DataCharacteristic extends bleno.Characteristic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sendNotidy(str) {
|
sendNotidy (str) {
|
||||||
if (!this._notifyFunc) return
|
if (!this._notifyFunc) return
|
||||||
this._notifyFunc(Buffer.from(str))
|
this._notifyFunc(Buffer.from(str))
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubscribe(maxValueSize, cb) {
|
onSubscribe (maxValueSize, cb) {
|
||||||
console.log(maxValueSize)
|
console.log(maxValueSize)
|
||||||
this._notifyFunc = cb
|
this._notifyFunc = cb
|
||||||
}
|
}
|
||||||
|
|
||||||
onUnsubscribe() {
|
onUnsubscribe () {
|
||||||
this._notifyFunc = null
|
this._notifyFunc = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
ble/index.js
13
ble/index.js
|
@ -1,24 +1,21 @@
|
||||||
|
const config = require('../config.json')
|
||||||
const bleno = require('bleno')
|
const bleno = require('bleno')
|
||||||
const adapterName = 'BLE_Printer'
|
const adapterName = 'BLE_Printer'
|
||||||
const serverUUID = config.uuid.main
|
const serverUUID = config.uuid.main
|
||||||
const localEvent = require('./localEvent')
|
const localEvent = require('./localEvent') //eslint-disable-line
|
||||||
const fs = require('fs')
|
|
||||||
const MainService = require('./main-service')
|
const MainService = require('./main-service')
|
||||||
|
|
||||||
bleno.on('stateChange', state => {
|
bleno.on('stateChange', state => {
|
||||||
console.log(`bt device state ${state}`)
|
console.log(`bt device state ${state}`)
|
||||||
if (state == 'poweredOn') {
|
if (state === 'poweredOn') {
|
||||||
|
bleno.startAdvertising(adapterName, [serverUUID])
|
||||||
bleno.startAdvertising(adapterName, [serverUUID], (error) => {
|
|
||||||
|
|
||||||
})
|
|
||||||
} else {
|
} else {
|
||||||
bleno.stopAdvertising()
|
bleno.stopAdvertising()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
bleno.on('advertisingStart', function (error) {
|
bleno.on('advertisingStart', function (error) {
|
||||||
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
|
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'))
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
bleno.setServices([new MainService()], error => {
|
bleno.setServices([new MainService()], error => {
|
||||||
|
|
|
@ -6,7 +6,7 @@ const GdataCharacteristic = require('./gdata-characteristic')
|
||||||
const dataCharacteristic = new GdataCharacteristic()
|
const dataCharacteristic = new GdataCharacteristic()
|
||||||
|
|
||||||
class MainService extends bleno.PrimaryService {
|
class MainService extends bleno.PrimaryService {
|
||||||
constructor() {
|
constructor () {
|
||||||
super({
|
super({
|
||||||
uuid: config.uuid.service.id,
|
uuid: config.uuid.service.id,
|
||||||
characteristics: [
|
characteristics: [
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
const bleno = require('bleno')
|
|
||||||
const config = require('./config.json')
|
|
||||||
|
|
||||||
class TimeCharacteristic extends bleno.Characteristic {
|
|
||||||
constructor() {
|
|
||||||
super({
|
|
||||||
uuid: config.uuid.service.func.time,
|
|
||||||
properties: ['read'],
|
|
||||||
descriptors: [
|
|
||||||
new bleno.Descriptor({
|
|
||||||
uuid: '88ff',
|
|
||||||
value: 'Now Time'
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onReadRequest(offset, callback) {
|
|
||||||
console.log(`offset :: ${offset}`)
|
|
||||||
callback(this.RESULT_SUCCESS, new Buffer(`${Date.now()}`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = TimeCharacteristic
|
|
|
@ -1,10 +1,10 @@
|
||||||
const EventEmitter = require('events')
|
const EventEmitter = require('events')
|
||||||
const util = require('util')
|
const util = require('util') //eslint-disable-line
|
||||||
|
|
||||||
class LocalEvent extends EventEmitter {
|
class LocalEvent extends EventEmitter {
|
||||||
constructor(){
|
constructor () { // eslint-disable-line
|
||||||
super()
|
super()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new LocalEvent()
|
module.exports = new LocalEvent()
|
||||||
|
|
|
@ -3,6 +3,9 @@
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"main": "app.js",
|
"main": "app.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"check":"standard --fix --verbose"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bleno": "^0.4.2",
|
"bleno": "^0.4.2",
|
||||||
"escpos": "^2.4.3",
|
"escpos": "^2.4.3",
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
html, body{
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1,12 +1,100 @@
|
||||||
|
/* eslint-disable no-throw-literal */
|
||||||
const KoaRouter = require('koa-router')
|
const KoaRouter = require('koa-router')
|
||||||
const router = new KoaRouter()
|
const router = new KoaRouter()
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
const Printer = require('../PrinterDev')
|
||||||
|
const KoaBody = require('koa-body')
|
||||||
|
const uuid = require('uuid')
|
||||||
|
|
||||||
|
router.use(async (c, n) => {
|
||||||
|
c.data = {
|
||||||
|
title: 'Printer System Setup'
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await n()
|
||||||
|
} catch (err) {
|
||||||
|
if (typeof err === 'string') {
|
||||||
|
c.body = err
|
||||||
|
} else {
|
||||||
|
c.body = err.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.async) {
|
||||||
|
c.body = {
|
||||||
|
status: 0,
|
||||||
|
msg: c.body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
router
|
router
|
||||||
.get('/', async (c, n) => {
|
.get('/', async (c, n) => {
|
||||||
c.redirect('/install')
|
c.redirect('/install')
|
||||||
})
|
})
|
||||||
.all('/install', async (c, n) => {
|
.get('/install', async (c, n) => {
|
||||||
c.body = 'install'
|
// get ttys
|
||||||
|
let ttys = await new Promise((resolve, reject) => {
|
||||||
|
fs.readdir(path.resolve('/dev'), (err, list) => {
|
||||||
|
if (err) return resolve([])
|
||||||
|
let arr = []
|
||||||
|
for (let it of list) {
|
||||||
|
if (it.startsWith('tty')) {
|
||||||
|
arr.push(path.resolve('/dev', it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resolve(arr)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
c.data.ttys = ttys
|
||||||
|
await c.render('install/index', c.data)
|
||||||
|
})
|
||||||
|
.post('/install/printer_test', KoaBody(), async (c, n) => {
|
||||||
|
c.async = true
|
||||||
|
let arr = c.request.body
|
||||||
|
if (!arr.device) throw '請輸入印表機連接埠'
|
||||||
|
let device = arr.device
|
||||||
|
let feed = arr.feed || 8
|
||||||
|
if (!isFinite(feed) || feed < 0) throw '切紙前換行必須是整數'
|
||||||
|
feed = typeof feed !== 'number' ? Math.floor(parseInt(feed)) : feed
|
||||||
|
|
||||||
|
Printer.serial = device
|
||||||
|
Printer.feed = feed
|
||||||
|
|
||||||
|
let status = await Printer.printTestPage()
|
||||||
|
|
||||||
|
if (!status) c.body = '測試失敗'
|
||||||
|
else c.body = '測試成功'
|
||||||
|
})
|
||||||
|
.post('/install/write_config', KoaBody(), async (c, n) => {
|
||||||
|
c.async = true
|
||||||
|
let arr = c.request.body
|
||||||
|
if (!arr.tty) throw '請輸入印表機連接埠'
|
||||||
|
if (!arr.ble || (arr.ble !== 'yes' && arr.ble !== 'no')) throw '請輸入藍牙啟用設定'
|
||||||
|
let feed = arr.feed || 8
|
||||||
|
if (!isFinite(feed) || feed < 0) throw '切紙前換行必須是整數'
|
||||||
|
feed = typeof feed !== 'number' ? Math.floor(parseInt(feed)) : feed
|
||||||
|
|
||||||
|
let json = {
|
||||||
|
ble: {
|
||||||
|
enable: false,
|
||||||
|
uuid: {
|
||||||
|
main: '',
|
||||||
|
service: '',
|
||||||
|
characteristic: ''
|
||||||
|
},
|
||||||
|
printer: {
|
||||||
|
serial: '',
|
||||||
|
feed: 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json.ble.enable = arr.ble === 'yes'
|
||||||
|
json.ble.uuid.main = uuid.v4()
|
||||||
|
json.ble.uuid.service = uuid.v4()
|
||||||
|
json.ble.uuid.characteristic = uuid.v4()
|
||||||
})
|
})
|
||||||
|
|
||||||
module.exports = router
|
module.exports = router
|
||||||
|
|
|
@ -26,7 +26,7 @@ try {
|
||||||
resolve(1)
|
resolve(1)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
await chk
|
await chk //eslint-disable-line
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setupMode = true
|
setupMode = true
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||||
|
<title><%- title %></title>
|
||||||
|
<link rel="stylesheet" href="/css/semantic.min.css">
|
||||||
|
<link rel="stylesheet" href="/css/main.css">
|
||||||
|
<script src="/js/jquery-3.2.1.min.js"></script>
|
||||||
|
<script src="/js/semantic.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
|
@ -0,0 +1,38 @@
|
||||||
|
<%- include ../includes/header.ejs %>
|
||||||
|
|
||||||
|
<div class="ui container" style="padding-top: 20px;">
|
||||||
|
<h1 class="ui header">系統安裝設定</h1>
|
||||||
|
<form id="setup" class="ui form">
|
||||||
|
<h3 class="ui dividing header">印表機設定</h3>
|
||||||
|
<div class="field">
|
||||||
|
<label for="tty">印表機連接埠</label>
|
||||||
|
<select name="tty" id="tty">
|
||||||
|
<option value="">選擇裝置</option>
|
||||||
|
<% for(let i of ttys) { %>
|
||||||
|
<option value="<%= i %>"><%= i %></option>
|
||||||
|
<% } %>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<label for="feed">切紙前空行</label>
|
||||||
|
<input type="text" name="feed" value="8" id="feed">
|
||||||
|
</div>
|
||||||
|
<div class="field">
|
||||||
|
<button class="ui button mini" type="button" id="test-printer">測試印表機</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 class="ui dividing header">藍芽列印設定</h3>
|
||||||
|
<div class="field">
|
||||||
|
<div class="ui checkbox">
|
||||||
|
<input type="checkbox" class="hidden" id="en-ble">
|
||||||
|
<label for="en-ble">啟用藍芽</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="margin-top: 40px; text-align: right;">
|
||||||
|
<button class="ui button blue" type="submit">送出設定</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%- include ../includes/footer.ejs %>
|
Loading…
Reference in New Issue