Newer
Older
// file system to load / look at our available modules / edit them
const fs = require('fs')
// express serves files, http makes the connection
const app = require('express')()
const http = require('http').Server(app)
// websocket does websocket
const WebSocket = require('ws')
// serving this handful of static files
app.get('/', (req, res) => {
console.log('client req /')
res.sendFile(__dirname + '/client/index.html')
})
app.get('/:file', (req, res) => {
console.log('client req', req.params.file)
res.sendFile(__dirname + '/client/' + req.params.file)
})
// and listening for requests here
const wss = new WebSocket.Server({ port: 8081 })
wss.on('connection', (ws) => {
sckt = ws
// say hello
console.log('socket open on 8081')
ws.on('message', (evt) => {
socketRecv(evt)
})
})
// through this window
http.listen(8080, () => {
console.log('listening on 8080 for static files')
})
var sckt = null
if (sckt) {
var msg = {
type: type,
data: data
}
sckt.send(JSON.stringify(msg))
var recv = JSON.parse(evt)
var type = recv.type
var data = recv.data
console.log('RECV CONSOLE:', data)
break
case 'get menu':
var tree = buildMenu()
socketSend('put menu', tree)
break
case 'add module':
addModule(data)
break
putLink(data)
case 'put ui':
changeUi(data)
break
console.log('ERR server recv with non recognized type', recv)
------------------------------------------------------
------------------------------------------------------
*/
var modules = new Array()
// wrap require() up, appending path used to object, and giving ID
// use the same to load from browser
var term = addModule('./src/ui/terminal.js')
var multiline = addModule('./src/ui/multiline.js')
var button = addModule('./src/ui/button.js')
var numOut = addModule('./src/ui/number.js')
var gcode = addModule('./src/parsing/gcode.js')
var planner = addModule('./src/motion/planner.js')
var xm = addModule('./src/hardware/stepper.js')
var yma = addModule('./src/hardware/stepper.js')
var ymb = addModule('./src/hardware/stepper.js')
var zm = addModule('./src/hardware/stepper.js')
var t1 = addModule('./src/hardware/test.js')
var t2 = addModule('./src/hardware/test.js')
var t3 = addModule('./src/hardware/test.js')
var t4 = addModule('./src/hardware/test.js')
var t5 = addModule('./src/hardware/test.js')
var bridge = addModule('./src/hardware/bridge.js')
term.outputs.lineOut.attach(gcode.inputs.lineIn)
multiline.outputs.lineOut.attach(gcode.inputs.lineIn)
gcode.outputs.instructionOut.attach(planner.inputs.instruction)
button.outputs.whammy.attach(numOut.inputs.evt)
numOut.outputs.out.attach(multiline.inputs.req)
button.outputs.whammy.attach(delay.inputs.thru)
delay.outputs.out.attach(planner.inputs.run)
// bi-directional hook planner / motor
planner.outputs.moves.attach(xm.inputs.move)
xm.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moves.attach(yma.inputs.move)
yma.outputs.ack.attach(planner.inputs.acks)
planner.outputs.moves.attach(ymb.inputs.move)
planner.outputs.moves.attach(zm.inputs.move)
zm.outputs.ack.attach(planner.inputs.acks)
// same motors / bridge
xm.state.axis = 'X'
xm.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(xm.inputs.packet)
bridge.state.rA = '0,3'
t1.outputs.packet.attach(bridge.inputs.A)
bridge.outputs.A.attach(t1.inputs.packet)
yma.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(yma.inputs.packet)
bridge.state.rB = '0,0'
t2.outputs.packet.attach(bridge.inputs.B)
bridge.outputs.B.attach(t2.inputs.packet)
// should have to reverse this but did it with wires :|
ymb.outputs.packet.attach(bridge.inputs.C)
bridge.outputs.C.attach(ymb.inputs.packet)
bridge.state.rC = '0,5'
t3.outputs.packet.attach(bridge.inputs.C)
bridge.outputs.C.attach(t3.inputs.packet)
zm.outputs.packet.attach(bridge.inputs.D)
bridge.outputs.D.attach(zm.inputs.packet)
bridge.state.rD = '0,1'
t4.outputs.packet.attach(bridge.inputs.D)
bridge.outputs.D.attach(t4.inputs.packet)
t5.outputs.packet.attach(bridge.inputs.E)
bridge.outputs.E.attach(t5.inputs.packet)
bridge.state.rE = '0'
// setting data w/r/t the representations they serve
setUiPos(multiline, 10, 10)
setUiPos(gcode, 450, 10)
setUiPos(term, 450, 180)
setUiPos(button, 450, 300)
setUiPos(numOut, 450, 400)
setUiPos(delay, 450, 520)
var plCol = 900
setUiPos(t1, plCol, 730)
setUiPos(t2, plCol, 850)
setUiPos(t3, plCol, 970)
setUiPos(t4, plCol, 1090)
setUiPos(t5, plCol, 1210)
setUiPos(planner, plCol, 10)
setUiPos(xm, hwCol, 10)
setUiPos(yma, hwCol, 250)
setUiPos(ymb, hwCol, 490)
setUiPos(zm, hwCol, 730)
planner.state.isRunning = 0
term.state.uiInput = "G1 X0"
term.state.uiInput = "G1 Y0"
planner.state.isRunning = 1
term.state.uiInput = "G1 X0 Y10"
term.state.uiInput = "G1 X-1 Y0"
term.state.uiInput = "G1 X0 Y0"
*/
function setUiPos(module, left, top){
if(module.ui == null){
module.ui = {}
}
module.ui.left = left
module.ui.top = top
}
/*
------------------------------------------------------
PROGRAM WRITING
------------------------------------------------------
function addModule(path) {
// get and add to server system
if (fs.existsSync(path)) {
var src = require(path) // get and return
var mod = new src() // make a new one
modules.push(mod) // add to the system
// assign and id and remember from whence it came
mod.path = path
// we need to add some top-level info to the inputs so that we can draw them
mod.inputs[item].parentId = mod.id
mod.inputs[item].key = item
}
for (item in mod.state) {
if (item == 'onChange' | item == 'emitChange' | item == 'emitters') {
//console.log('rolling past change fn')
} else {
mod.state['_' + item] = mod.state[item]
mod.state[item] = {}
console.log('ADDING MODULE', mod)
// first to UI
// also to fn call, in case writing program ?
return mod
console.log('ERR no module found at', path)
function writeStateObject(mod, item) {
Object.defineProperty(mod.state, item, {
set: function(x) {
this['_' + item] = x
this.emitChange(item)
// update server (or in some cases, a confirmation)
putState(mod)
get: function() {
return this['_' + item]
}
})
}
/*
PROGRAM UPDATING
*/
//console.log('modules at prgmem start', modules)
function putReps() {
reps.push(makeRep(modules[mod]))
// scrape for only things we'll want to represent
var rep = {
id: mod.id,
description: mod.description,
inputs: mod.inputs,
outputs: mod.outputs,
state: {}
}
// holds UI information - to load mods at location
for (var key in mod.state) {
if (isStateKey(key)) {
return rep
}
function putRep(mod) {
socketSend('add rep', makeRep(mod))
}
socketSend('change rep', makeRep(mod))
}
// update state from UI to server
function changeState(data) {
// of one module
// should just recv all state, walk tree for differences
var oldState = modules[data.id].state
var newState = data.state
// rep only holds proper key-values w/o emitters, _values etc
if (oldState[key].isButton) {
if (oldState[key].isPressed != newState[key].isPressed) {
console.log('CHANGE BUTTON STATE', key, 'to', newState[key], 'in', data.id)
// this will trigger some 'onChange' f'ns
// that might change some state
// to prevent quickly changing it back, we'll exit now (one state change from UI per trx)
return true
} else if (oldState[key].isMultiLine) {
if (oldState[key].value != newState[key].value){
console.log('CHANGE MULTILINE STATE', key, 'to', newState[key].value, 'in', data.id)
oldState[key].value = newState[key].value
return true
}
console.log('CHANGE STATE', key, 'to', newState[key], 'in', data.id)
console.log("NO UI")
mod.ui = {}
}
mod.ui = data.ui
console.log('CHANGE UI', mod.id, mod.ui)
}
function isStateKey(key) {
if (key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange') {
return false
} else {
return true
}
}
// push new state from server to UI
function putState(mod) {
// push just the state to the individual mod
for (var key in mod.state) {
if (isStateKey(key)) {
socketSend('change state', data)
function putLink(data) {
var fromModule = modules.find((module) => {
return module.id === data.from.id
})
var toModule = modules.find((module) => {
return module.id === data.to.id
})
if(fromModule.outputs[data.from.output].isLinked(toModule.inputs[data.to.input])){
console.log("HOOKDOWN")
fromModule.outputs[data.from.output].remove(toModule.inputs[data.to.input])
} else {
fromModule.outputs[data.from.output].attach(toModule.inputs[data.to.input])
}
// replace it
changeRep(fromModule)
tree[dir[i]] = {}
var subdir = fs.readdirSync('./src/' + dir[i])
var obj = {}
obj.path = './src/' + dir[i] + '/' + subdir[j]
tree[dir[i]][subdir[j].slice(0, -3)] = obj
}
}
}