2018-05-07 05:25:53 +00:00
|
|
|
const dgram = require('dgram')
|
|
|
|
const server = dgram.createSocket('udp4')
|
|
|
|
const net = require('net')
|
|
|
|
const WebSocket = require('ws')
|
|
|
|
|
|
|
|
let lego = {
|
|
|
|
sn: null,
|
|
|
|
port: null,
|
|
|
|
name: null,
|
|
|
|
proto: null,
|
|
|
|
addr: null,
|
|
|
|
connected: false
|
|
|
|
}
|
|
|
|
let legoClient = null
|
|
|
|
|
|
|
|
function padleft(v, n) {
|
|
|
|
if (typeof v !== 'string') v = v.toString()
|
|
|
|
if (v.length < n) {
|
|
|
|
return padleft(`0${v}`, n)
|
|
|
|
}
|
|
|
|
return v
|
|
|
|
}
|
|
|
|
|
|
|
|
function convertLength(num, blng = 1) {
|
|
|
|
let str = num.toString(16)
|
|
|
|
let tlng = blng * 2
|
|
|
|
|
|
|
|
switch (str.length) {
|
|
|
|
case 1:
|
|
|
|
if (tlng > 2) return `0${str}00`
|
|
|
|
else return `0${str}`
|
|
|
|
case 2:
|
|
|
|
if (tlng > 2) return `${str}00`
|
|
|
|
else return `${str}`
|
|
|
|
case 3:
|
|
|
|
return `${str.substr(-2)}0${str.substr(0, 1)}`
|
|
|
|
case 4:
|
|
|
|
return `${str.substr(-2)}${str.substr(0, 2)}`
|
|
|
|
}
|
|
|
|
|
|
|
|
return padleft('0', tlng)
|
|
|
|
}
|
|
|
|
|
|
|
|
function getMsgByte(name, val) {
|
|
|
|
let name_buf = Buffer.from(name)
|
|
|
|
name_buf = Buffer.concat([name_buf, Buffer.from([0x00])], (name_buf.length + 1))
|
|
|
|
let name_lng = name_buf.length
|
|
|
|
|
|
|
|
let val_buf = null
|
|
|
|
if (typeof val === 'number') {
|
|
|
|
val_buf = Buffer.allocUnsafe(4)
|
|
|
|
val_buf.writeFloatLE(val)
|
|
|
|
} else {
|
|
|
|
if (typeof val !== 'string') val.toString()
|
|
|
|
val_buf = Buffer.from(val)
|
|
|
|
val_buf = Buffer.concat([val_buf, Buffer.from([0x00])], (val_buf.length + 1))
|
|
|
|
}
|
|
|
|
if (val_buf === null) return null
|
|
|
|
let val_lng = val_buf.length
|
|
|
|
|
|
|
|
return `${convertLength(name_lng, 1)}${name_buf.toString('hex')}${convertLength(val_lng, 2)}${val_buf.toString('hex')}`
|
|
|
|
}
|
|
|
|
|
|
|
|
server.on('error', err => {
|
|
|
|
console.log('error ', err)
|
|
|
|
server.close()
|
|
|
|
})
|
|
|
|
server.on('message', (msg, rinfo) => {
|
|
|
|
console.log('message', msg.toString())
|
|
|
|
console.log('rinfo', rinfo)
|
|
|
|
let str = msg.toString()
|
|
|
|
let regex = /Serial\-Number:\s(\w+)\r\nPort:\s(\d+)\r\nName:\s(\w+)\r\nProtocol:\s(\w+)/
|
|
|
|
let match = str.match(regex)
|
|
|
|
if (match.length > 4) {
|
|
|
|
lego.sn = match[1]
|
|
|
|
lego.port = match[2]
|
|
|
|
lego.name = match[3]
|
|
|
|
lego.proto = match[4]
|
|
|
|
}
|
|
|
|
lego.addr = rinfo.address
|
|
|
|
console.log('lego info ', lego)
|
|
|
|
|
|
|
|
let client = dgram.createSocket('udp4')
|
|
|
|
client.send(Buffer.from([0x01]), lego.port, lego.addr, (err) => {
|
|
|
|
if (err) {
|
|
|
|
console.log('send udp error')
|
|
|
|
client.close()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
server.close()
|
|
|
|
} catch (err) { }
|
|
|
|
|
|
|
|
connectEV3()
|
|
|
|
|
|
|
|
try {
|
|
|
|
client.close()
|
|
|
|
} catch (err) { }
|
|
|
|
})
|
|
|
|
})
|
|
|
|
server.bind(3015)
|
|
|
|
|
|
|
|
async function connectEV3() {
|
|
|
|
legoClient = net.createConnection({
|
|
|
|
port: lego.port,
|
|
|
|
host: lego.addr
|
|
|
|
}, () => {
|
|
|
|
console.log('connected')
|
|
|
|
console.log('send unlock')
|
|
|
|
legoClient.write(`GET /target?sn=${lego.sn} VMTP1.0\nProtocol: ${lego.proto}`)
|
|
|
|
})
|
|
|
|
|
|
|
|
legoClient.on('data', data => {
|
|
|
|
console.log('get ev3 data', data.toString())
|
|
|
|
let str = data.toString()
|
|
|
|
if (/Accept/i.test(str)) {
|
|
|
|
lego.connected = true
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
legoClient.on('end', () => {
|
|
|
|
console.log('connect end')
|
|
|
|
legoClient = null
|
|
|
|
lego.connected = false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
const ws = new WebSocket.Server({
|
|
|
|
port: 9999
|
|
|
|
})
|
|
|
|
|
|
|
|
ws.on('connection', client => {
|
|
|
|
client.on('message', msg => {
|
|
|
|
console.log(msg)
|
|
|
|
let s = ''
|
|
|
|
let wbuf = null
|
|
|
|
let lng = 0
|
|
|
|
switch (msg) {
|
|
|
|
case 'check':
|
|
|
|
client.send(`ev3 connect: ${lego.connected}`)
|
|
|
|
break
|
|
|
|
case 'forward':
|
|
|
|
if (!lego.connected) break
|
2018-05-09 10:09:08 +00:00
|
|
|
s = `0000819e${getMsgByte('a', 360 )}`
|
2018-05-07 05:25:53 +00:00
|
|
|
s = `${convertLength(s.length / 2, 2)}${s}`
|
|
|
|
wbuf = Buffer.from(s, 'hex')
|
|
|
|
console.log('write byte ', s)
|
|
|
|
legoClient.write(wbuf)
|
|
|
|
break
|
|
|
|
case 'back':
|
|
|
|
if (!lego.connected) break
|
2018-05-09 10:09:08 +00:00
|
|
|
s = `0000819e${getMsgByte('c', 360)}`
|
2018-05-07 05:25:53 +00:00
|
|
|
s = `${convertLength(s.length / 2, 2)}${s}`
|
|
|
|
wbuf = Buffer.from(s, 'hex')
|
|
|
|
console.log('write byte ', s)
|
|
|
|
legoClient.write(wbuf)
|
|
|
|
break
|
|
|
|
case 'click':
|
|
|
|
if (!lego.connected) break
|
|
|
|
s = `0000819e${getMsgByte('b', 90)}`
|
|
|
|
s = `${convertLength(s.length / 2, 2)}${s}`
|
|
|
|
wbuf = Buffer.from(s, 'hex')
|
|
|
|
console.log('write byte ', s)
|
|
|
|
legoClient.write(wbuf)
|
|
|
|
break
|
2018-05-09 10:09:08 +00:00
|
|
|
case 'right':
|
|
|
|
if (!lego.connected) break
|
|
|
|
s = `0000819e${getMsgByte('d', 180)}`
|
|
|
|
s = `${convertLength(s.length / 2, 2)}${s}`
|
|
|
|
wbuf = Buffer.from(s, 'hex')
|
|
|
|
console.log('write byte ', s)
|
|
|
|
legoClient.write(wbuf)
|
|
|
|
break
|
|
|
|
case 'left':
|
|
|
|
if (!lego.connected) break
|
|
|
|
s = `0000819e${getMsgByte('e', 180)}`
|
|
|
|
s = `${convertLength(s.length / 2, 2)}${s}`
|
|
|
|
wbuf = Buffer.from(s, 'hex')
|
|
|
|
console.log('write byte ', s)
|
|
|
|
legoClient.write(wbuf)
|
|
|
|
break
|
2018-05-07 05:25:53 +00:00
|
|
|
case 'restart':
|
|
|
|
process.exit(0)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
})
|
2018-05-09 10:09:08 +00:00
|
|
|
})
|