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 config = require('./config.json')
|
||||
// const config = require('./config.json')
|
||||
const fs = require('fs')
|
||||
const iconv = require('iconv-lite')
|
||||
|
||||
class PrinterDevice {
|
||||
constructor() {
|
||||
constructor () {
|
||||
this._serial = ''
|
||||
this._feed = 8
|
||||
this._isOpen = false
|
||||
this._device = null
|
||||
this._printer = null
|
||||
this._type = null // type = serial or console
|
||||
}
|
||||
|
||||
encodeStr(str){
|
||||
if(!str || typeof str != 'string') return false
|
||||
encodeStr (str) {
|
||||
if (!str || typeof str !== 'string') return false
|
||||
return iconv.encode(str, 'big5')
|
||||
}
|
||||
|
||||
async connect() {
|
||||
async connect () {
|
||||
let chkSerial = await new Promise((resolve, reject) => {
|
||||
fs.access(config.printer.serial, err => {
|
||||
fs.access(this._serial, err => {
|
||||
if (err) return resolve(false)
|
||||
return resolve(true)
|
||||
})
|
||||
})
|
||||
if (chkSerial) {
|
||||
this._device = new escpos.Serial(config.printer.serial)
|
||||
this._device = new escpos.Serial(this._serial)
|
||||
this._type = 'serial'
|
||||
} else {
|
||||
this._device = new escpos.Console()
|
||||
@ -35,8 +37,8 @@ class PrinterDevice {
|
||||
this.openSerial()
|
||||
}
|
||||
|
||||
async openSerial() {
|
||||
if (!this._device || this._type != 'serial') return
|
||||
async openSerial () {
|
||||
if (!this._device || this._type !== 'serial') return
|
||||
this._isOpen = await new Promise((resolve, reject) => {
|
||||
this._device.open(err => {
|
||||
if (err) return resolve(false)
|
||||
@ -45,7 +47,7 @@ class PrinterDevice {
|
||||
})
|
||||
}
|
||||
|
||||
async printerString(str) {
|
||||
async printerString (str) {
|
||||
if (!this._isOpen || !this._printer) return false
|
||||
|
||||
this._printer.font('a')
|
||||
@ -66,8 +68,8 @@ class PrinterDevice {
|
||||
case 's':
|
||||
let size = tmp.substring(2)
|
||||
let sarr = size.trim().split(',')
|
||||
if (sarr.length != 2) break
|
||||
if(!isFinite(sarr[0]) || !isFinite(sarr[1])) break
|
||||
if (sarr.length !== 2) break
|
||||
if (!isFinite(sarr[0]) || !isFinite(sarr[1])) break
|
||||
sarr = sarr.map(t => Math.floor(t))
|
||||
this._printer.size(sarr[0], sarr[1])
|
||||
break
|
||||
@ -77,26 +79,50 @@ class PrinterDevice {
|
||||
}
|
||||
}
|
||||
|
||||
this._printer.cut(true, config.printer.cutFeed || 4)
|
||||
this._printer.cut(true, this._feed || 4)
|
||||
|
||||
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._type == 'serial') {
|
||||
if (this._type === 'serial') {
|
||||
let self = this
|
||||
await new Promise((resolve, reject) => {
|
||||
self._printer.close(() => {
|
||||
self._printer = null
|
||||
self._isOpen = false
|
||||
resolve(1)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
get isOpen() {
|
||||
return this._isOpen ? true : false
|
||||
get isOpen () {
|
||||
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('./server')
|
||||
require('./server')
|
||||
|
@ -12,7 +12,7 @@ const notifyDesciptor = new bleno.Descriptor({
|
||||
})
|
||||
|
||||
class DataCharacteristic extends bleno.Characteristic {
|
||||
constructor() {
|
||||
constructor () {
|
||||
super({
|
||||
uuid: config.uuid.service.func.data,
|
||||
properties: ['write', 'writeWithoutResponse', 'notify'],
|
||||
@ -23,15 +23,15 @@ class DataCharacteristic extends bleno.Characteristic {
|
||||
this._notifyFunc = null
|
||||
}
|
||||
|
||||
onWriteRequest(data, offset, withoutResponse, callback) {
|
||||
onWriteRequest (data, offset, withoutResponse, callback) {
|
||||
console.log(`offset :: ${offset} , withoutRes :: ${withoutResponse}`)
|
||||
console.log(`get data`, data)
|
||||
|
||||
if (data.length == 1 && data[0] == 0x00) {
|
||||
if (data.length === 1 && data[0] === 0x00) {
|
||||
tmp = []
|
||||
idx = 0
|
||||
failFlag = false
|
||||
} else if (data.length == 1 && data[0] == 0xff) {
|
||||
} else if (data.length === 1 && data[0] === 0xff) {
|
||||
console.log(Buffer.from(tmp).toString())
|
||||
if (!failFlag) {
|
||||
localEvent.emit('print', Buffer.from(tmp).toString())
|
||||
@ -53,17 +53,17 @@ class DataCharacteristic extends bleno.Characteristic {
|
||||
}
|
||||
}
|
||||
|
||||
sendNotidy(str) {
|
||||
sendNotidy (str) {
|
||||
if (!this._notifyFunc) return
|
||||
this._notifyFunc(Buffer.from(str))
|
||||
}
|
||||
|
||||
onSubscribe(maxValueSize, cb) {
|
||||
onSubscribe (maxValueSize, cb) {
|
||||
console.log(maxValueSize)
|
||||
this._notifyFunc = cb
|
||||
}
|
||||
|
||||
onUnsubscribe() {
|
||||
onUnsubscribe () {
|
||||
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 adapterName = 'BLE_Printer'
|
||||
const serverUUID = config.uuid.main
|
||||
const localEvent = require('./localEvent')
|
||||
const fs = require('fs')
|
||||
const localEvent = require('./localEvent') //eslint-disable-line
|
||||
const MainService = require('./main-service')
|
||||
|
||||
bleno.on('stateChange', state => {
|
||||
console.log(`bt device state ${state}`)
|
||||
if (state == 'poweredOn') {
|
||||
|
||||
bleno.startAdvertising(adapterName, [serverUUID], (error) => {
|
||||
|
||||
})
|
||||
if (state === 'poweredOn') {
|
||||
bleno.startAdvertising(adapterName, [serverUUID])
|
||||
} else {
|
||||
bleno.stopAdvertising()
|
||||
}
|
||||
})
|
||||
|
||||
bleno.on('advertisingStart', function (error) {
|
||||
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'));
|
||||
console.log('on -> advertisingStart: ' + (error ? 'error ' + error : 'success'))
|
||||
|
||||
if (!error) {
|
||||
bleno.setServices([new MainService()], error => {
|
||||
|
@ -6,7 +6,7 @@ const GdataCharacteristic = require('./gdata-characteristic')
|
||||
const dataCharacteristic = new GdataCharacteristic()
|
||||
|
||||
class MainService extends bleno.PrimaryService {
|
||||
constructor() {
|
||||
constructor () {
|
||||
super({
|
||||
uuid: config.uuid.service.id,
|
||||
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 util = require('util')
|
||||
const util = require('util') //eslint-disable-line
|
||||
|
||||
class LocalEvent extends EventEmitter {
|
||||
constructor(){
|
||||
constructor () { // eslint-disable-line
|
||||
super()
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new LocalEvent()
|
||||
module.exports = new LocalEvent()
|
||||
|
@ -3,6 +3,9 @@
|
||||
"version": "0.0.1",
|
||||
"main": "app.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"check":"standard --fix --verbose"
|
||||
},
|
||||
"dependencies": {
|
||||
"bleno": "^0.4.2",
|
||||
"escpos": "^2.4.3",
|
||||
|
5
public/css/main.css
Normal file
5
public/css/main.css
Normal file
@ -0,0 +1,5 @@
|
||||
html, body{
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: #eee;
|
||||
}
|
364
public/css/semantic.min.css
vendored
Executable file
364
public/css/semantic.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
4
public/js/jquery-3.2.1.min.js
vendored
Normal file
4
public/js/jquery-3.2.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/js/jquery-3.2.1.min.map
Normal file
1
public/js/jquery-3.2.1.min.map
Normal file
File diff suppressed because one or more lines are too long
19
public/js/semantic.min.js
vendored
Executable file
19
public/js/semantic.min.js
vendored
Executable file
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 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
|
||||
.get('/', async (c, n) => {
|
||||
c.redirect('/install')
|
||||
})
|
||||
.all('/install', async (c, n) => {
|
||||
c.body = 'install'
|
||||
.get('/install', async (c, n) => {
|
||||
// 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)
|
||||
})
|
||||
})
|
||||
await chk
|
||||
await chk //eslint-disable-line
|
||||
} catch (err) {
|
||||
setupMode = true
|
||||
}
|
||||
|
2
views/includes/footer.ejs
Normal file
2
views/includes/footer.ejs
Normal file
@ -0,0 +1,2 @@
|
||||
</body>
|
||||
</html>
|
13
views/includes/header.ejs
Normal file
13
views/includes/header.ejs
Normal file
@ -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>
|
38
views/install/index.ejs
Normal file
38
views/install/index.ejs
Normal file
@ -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
Block a user