From d7e22dbce4bcfcf19f30a6b1cbd7dc094df2796f Mon Sep 17 00:00:00 2001
From: Jake <jake.read@cba.mit.edu>
Date: Mon, 26 Nov 2018 16:39:13 -0500
Subject: [PATCH] more work button

---
 README.md                              |   2 +-
 client/client.js                       |   4 +-
 client/ui/uiButton.js                  |   8 +-
 lib/atkroute.js                        |  37 -------
 lib/atkunit.js                         |  59 ------------
 lib/cartesian.js                       |  28 ------
 lib/jsunit.js                          | 128 -------------------------
 lib/packets.js                         |  24 -----
 modules/hardware/atkbreadboardboard.js |   2 +-
 modules/hardware/atkmrobot.js          |   2 +-
 modules/hardware/atkseriallink.js      |  16 +++-
 modules/hardware/atkstepper.js         |   9 +-
 modules/hardware/webcam.js             |   2 +-
 modules/motion/planner.js              |   4 +-
 modules/ui/number.js                   |   2 +-
 modules/ui/stest.js                    |   4 +
 modules/ui/terminal.js                 |   2 +-
 modules/util/delay.js                  |   2 +-
 programs.js                            |  10 +-
 src/atkunit.js                         |  24 ++++-
 src/jsunit.js                          |   2 +-
 src/ui/uiButton.js                     |   9 +-
 22 files changed, 78 insertions(+), 302 deletions(-)
 delete mode 100644 lib/atkroute.js
 delete mode 100644 lib/atkunit.js
 delete mode 100644 lib/cartesian.js
 delete mode 100644 lib/jsunit.js
 delete mode 100644 lib/packets.js

diff --git a/README.md b/README.md
index 665d878..6a0930c 100644
--- a/README.md
+++ b/README.md
@@ -175,7 +175,7 @@ function uiNum() {
     var state = uinum.state 
 
     state.number = 10
-    state.onChange('number', onNumberDesire)
+    state.onUiChange('number', onNumberDesire)
 
     state.button = Button('WHAM', onNumberDesire)
 
diff --git a/client/client.js b/client/client.js
index 45a73a0..75985c2 100644
--- a/client/client.js
+++ b/client/client.js
@@ -316,8 +316,8 @@ function redrawLinks() {
         svg.removeChild(svg.firstChild)
     }
     // draw origin 
-    var og1 = newLine(-15, 0, 15, 0, 5, false)
-    var og2 = newLine(0, -15, 0, 15, 5, false)
+    var og1 = newLine(20, 30, 40, 30, 3, false)
+    var og2 = newLine(30, 20, 30, 40, 3, false)
     // find that link
     var lnkPt
     var nLnk = 0
diff --git a/client/ui/uiButton.js b/client/ui/uiButton.js
index 3d8f021..82d0935 100644
--- a/client/ui/uiButton.js
+++ b/client/ui/uiButton.js
@@ -44,6 +44,12 @@
 		btn.key = key 
 		// affectionately named lump of code, insert ourselves here 
 		program.modules[id].ui[key].lump = btn 
-		socketSend('console', 'hello from' + btn.parentId + btn.key)
+		// and call-back to do onload things
+		var data = {
+			id: btn.parentId,
+			key: btn.key,
+			msg: 'onload'
+		}
+		socketSend('put ui change', data)
 	}
 })()
\ No newline at end of file
diff --git a/lib/atkroute.js b/lib/atkroute.js
deleted file mode 100644
index 02c2ba4..0000000
--- a/lib/atkroute.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// object to extend for things-that-are-hardware
-
-// and pass f'n to call on received messages
-function ATKRoute(route, calls) {
-    var atkroute = {
-        isAtkRoute: true,
-        link: null, // pls, deliver 2 me a hw outlet 
-        route: route,
-        calls: {}
-    }
-
-    atkroute.send = function(msg) {
-        if (this.link != null) {
-            // CHECKS and append route, then send 
-            this.link.send(msg, this)
-        } else {
-            console.log("NO LINK NO SEND")
-        }
-    }
-
-    atkroute.subscribe = function(key, callback){
-        this.calls[key.toString()] = callback
-    }
-
-    atkroute.onMessage = function(msg){
-        // one key at a time, for now
-        var key = msg[0].toString()
-        // *could* slice the key out at this point, but nah 
-        if(this.calls[key] != null){
-            this.calls[key](msg)
-        }
-    }
-
-    return atkroute
-}
-
-module.exports = ATKRoute
\ No newline at end of file
diff --git a/lib/atkunit.js b/lib/atkunit.js
deleted file mode 100644
index 08e7f12..0000000
--- a/lib/atkunit.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// software object for reciprocal hardware object 
-
-// boilerplate atkapi header
-const InOut = require('./jsunit.js')
-let Input = InOut.Input
-let Output = InOut.Output
-let State = InOut.State
-let Button = InOut.Button
-
-let ATKRoute = require('./atkroute.js')
-
-function Hardware(){
-	var hardware = {
-		description:{
-			name: 'hardwareUnit',
-			alt: 'software representation of networked hardware object',
-			isHardware: true 
-		},
-		route: ATKRoute('0,0')
-	}
-
-	hardware.state = State()
-	var state = hardware.state 
-
-	state.reset = Button('reset hardware', onReset)
-
-	state.test = Button('test network', onNetworkTest)
-	state.message = 'click above to test network'
-	state.route = '0,0' // default  
-
-	state.onChange('route', function(){
-		hardware.route.route = state.route 
-	})
-
-	function onReset(){
-		var rstpck = new Array()
-		rstpck.push(128)
-		state.message = 'reset command issued'
-		hardware.route.send(rstpck)
-	}
-
-	function onNetworkTest(){
-		var tstpck = new Array()
-		tstpck.push(127)
-		state.message = 'test packet out'
-		hardware.route.send(tstpck)
-	}
-
-	hardware.route.subscribe(127, testReturn)
-
-	function testReturn(msg){
-		state.message = 'test OK'
-		console.log('test returns with msg', msg)
-	}
-
-	return hardware
-}
-
-module.exports = Hardware
\ No newline at end of file
diff --git a/lib/cartesian.js b/lib/cartesian.js
deleted file mode 100644
index c6255fe..0000000
--- a/lib/cartesian.js
+++ /dev/null
@@ -1,28 +0,0 @@
-function distance(p1, p2) {
-    // takes p1, p2 to be arrays of same length
-    // computes cartesian distance
-    var sum = 0
-    for (var i = 0; i < p1.length; i++) {
-        sum += Math.pow((p1[i] - p2[i]), 2)
-    }
-    return Math.sqrt(sum)
-}
-
-function length(v) {
-    // length of vector
-    var sum = 0
-    for (var i = 0; i < v.length; i++) {
-        sum += Math.pow(v[i], 2)
-    }
-    return Math.sqrt(sum)
-}
-
-function degrees(rad){
-    return rad * (180 / Math.PI)
-}
-
-module.exports = {
-    distance: distance,
-    length: length,
-    degrees: degrees
-}
\ No newline at end of file
diff --git a/lib/jsunit.js b/lib/jsunit.js
deleted file mode 100644
index 084bc36..0000000
--- a/lib/jsunit.js
+++ /dev/null
@@ -1,128 +0,0 @@
-// event system to include type-checking etc
-// dataflow types for javascript objects ... 
-
-function Input(type, fn) {
-    var input = {
-        accepts: type,
-        fn: fn
-    }
-
-    return input
-}
-
-function Output(type) {
-    var output = {
-        emits: type
-    }
-
-    output.calls = new Array()
-
-    output.attach = function(input) {
-        this.calls.push(input)
-    }
-
-    output.isLinked = function(input) {
-        // return true if already hooked up 
-        if (this.calls.includes(input)) {
-            return true
-        } else {
-            return false
-        }
-    }
-
-    output.remove = function(input) {
-        if (!this.isLinked(input)) {
-            console.log('attempt to rm input that is not attached')
-            return false
-        } else {
-            this.calls.splice(this.calls.indexOf(input), 1)
-        }
-    }
-
-    output.removeAllLinks = function() {
-        this.calls = []
-    }
-
-    output.checkLinks = function(id){
-    	console.log('checking links', this)
-    	for(index in this.calls){
-    		if(this.calls[index].parentId == id){
-    			console.log('popping null entry from', this.calls)
-    			this.calls.splice(index, 1)
-    			console.log('new record', this.calls)
-    		} else {
-    			// all good 
-    		}
-    	}
-    }
-
-    output.emit = function(data) {
-        if (this.calls.length == 0) {
-            console.log('no inputs bound to this output')
-        } else {
-            for (index in this.calls) {
-                this.calls[index].fn(JSON.parse(JSON.stringify(data)))
-            }
-        }
-    }
-
-    return output
-}
-
-function State() {
-    var state = {}
-
-    state.emitters = {}
-
-    state.onChange = function(item, fn) {
-        this.emitters[item] = fn
-    }
-
-    state.emitChange = function(item) {
-        if (this.emitters[item] != null) {
-            this.emitters[item]()
-        }
-    }
-
-    return state
-}
-
-function isStateKey(key) {
-    if (key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange') {
-        return false
-    } else {
-        return true
-    }
-}
-
-// a coupl'a fancy UI state hooks 
-function Button(label, onClick) {
-    var button = {
-        type: 'button',
-        label: label,
-        onClick: onClick
-    }
-
-    return button
-}
-
-// now we're definitely writing a UI class 
-function MultiLine(label, rows) {
-    var ml = {
-        type: 'multiline',
-        label: label,
-        rows: rows,
-        value: ''
-    }
-
-    return ml
-}
-
-module.exports = {
-    Input: Input,
-    Output: Output,
-    State: State,
-    isStateKey: isStateKey,
-    Button: Button,
-    MultiLine: MultiLine
-}
\ No newline at end of file
diff --git a/lib/packets.js b/lib/packets.js
deleted file mode 100644
index ad63359..0000000
--- a/lib/packets.js
+++ /dev/null
@@ -1,24 +0,0 @@
-function pack32(val) {
-    var pack = new Array();
-    pack[0] = (val >> 24) & 255;
-    pack[1] = (val >> 16) & 255;
-    pack[2] = (val >> 8) & 255;
-    pack[3] = val & 255;
-
-    return pack;
-}
-
-function unPack32(arr){
-	if(arr.length == 4){
-		var unPacked = arr[0] << 24 | arr[1] << 16 | arr[2] << 8 | arr[3] 
-		return unPacked
-	} else {
-		console.log("ERR: arr > 4 at unPack32", arr)
-	}
-	
-}
-
-module.exports = {
-	pack32: pack32,
-	unPack32: unPack32
-}
\ No newline at end of file
diff --git a/modules/hardware/atkbreadboardboard.js b/modules/hardware/atkbreadboardboard.js
index 98bfd27..6a546c2 100644
--- a/modules/hardware/atkbreadboardboard.js
+++ b/modules/hardware/atkbreadboardboard.js
@@ -35,7 +35,7 @@ function ATKBreadBoardBoard() {
 
     state.servoButton = Button('SEND VALUE', onServoValChange)
     state.servoVal = 0 // 0->100 does 1 -> 2ms duty on 20ms period
-    state.onChange('servoVal', onServoValChange)
+    state.onUiChange('servoVal', onServoValChange)
 
     state.adcButton = Button('REQUEST ADC CONVERSION', onADCRequest)
 
diff --git a/modules/hardware/atkmrobot.js b/modules/hardware/atkmrobot.js
index 70cf5d7..f80497b 100644
--- a/modules/hardware/atkmrobot.js
+++ b/modules/hardware/atkmrobot.js
@@ -33,7 +33,7 @@ function ATKMathRobot() {
 
     state.message = 'no packet yet'
     state.pc_t = 2048
-    state.onChange('pc_t', onPositionTargetUserChange)
+    state.onUiChange('pc_t', onPositionTargetUserChange)
     state.walk = 1024
     state.tickButton = Button('Walk Value', onPositionTickTock)
 
diff --git a/modules/hardware/atkseriallink.js b/modules/hardware/atkseriallink.js
index 2c2e672..21f88b3 100644
--- a/modules/hardware/atkseriallink.js
+++ b/modules/hardware/atkseriallink.js
@@ -2,9 +2,11 @@
 const JSUnit = require('../../src/jsunit.js')
 let Input = JSUnit.Input
 let Output = JSUnit.Output
-
 let State = JSUnit.State
-let Button = JSUnit.Button
+
+// interface elements
+const JSUI = require('../../src/jsui.js')
+let UI = JSUI.UI 
 
 const SerialPort = require('serialport')
 
@@ -23,9 +25,17 @@ function ATKSerialLink() {
     var state = atkSerialLink.state 
 
     state.portName = '---'
-    state.connect = Button('click to find and connect', findSerialPort)
     state.portStatus = 'closed' // or we hope it will be 
 
+    atkSerialLink.ui = UI() 
+    var ui = atkSerialLink.ui 
+
+    ui.addElement('kickButton', './ui/uiButton.js', findSerialPort)
+
+    ui.kickButton.onload = function(){
+        ui.kickButton.setText('click to find and connect')
+    }
+
     atkSerialLink.init = function(){
         //findSerialPort()
     }
diff --git a/modules/hardware/atkstepper.js b/modules/hardware/atkstepper.js
index d819b34..c928b5f 100644
--- a/modules/hardware/atkstepper.js
+++ b/modules/hardware/atkstepper.js
@@ -4,7 +4,6 @@ let Input = JSUnit.Input
 let Output = JSUnit.Output
 
 let State = JSUnit.State
-let Button = JSUnit.Button
 
 const MJS = require('mathjs')
 const DCRT = require('../../src/cartesian.js')
@@ -36,7 +35,7 @@ function Stepper() {
     // for acceleration moves, in steps/s/s 
     state.rate = 2000
 
-    state.onChange('rate', () => {
+    state.onUiChange('rate', () => {
         if(state.rate > 2000){
             state.rate = 2000 
         } else if (state.rate < 100){
@@ -48,7 +47,11 @@ function Stepper() {
     state.spu = 200 // steps per unit 
     state.rawMove = -10
 
-    state.makeMove = Button('test move', onRawMove)
+    var ui = stepper.ui 
+    ui.addElement('rawButton', './ui/uiButton.js', onRawMove)
+    ui.rawButton.onload = function(){
+        ui.rawButton.setText('click to send test move')
+    }
 
     state.lead = 0
     state.position = 0 // in steps 
diff --git a/modules/hardware/webcam.js b/modules/hardware/webcam.js
index 3ac82a7..87ed9c0 100644
--- a/modules/hardware/webcam.js
+++ b/modules/hardware/webcam.js
@@ -43,7 +43,7 @@ function WEBCAM() {
     var state = webcam.state
 
     state.button = Button('REQUEST IMAGE')
-    state.onChange('button', onButtonPress)
+    state.onUiChange('button', onButtonPress)
     state.counter = 0
 
     webcam.inputs = {
diff --git a/modules/motion/planner.js b/modules/motion/planner.js
index 04e088a..dff61e2 100644
--- a/modules/motion/planner.js
+++ b/modules/motion/planner.js
@@ -24,7 +24,7 @@ function Planner() {
     var state = planner.state // reference pass attempt?
 
     state.axisIDs = 'X,Y,Z'
-    state.onChange('axisIDs', axisIDUpdate)
+    state.onUiChange('axisIDs', axisIDUpdate)
 
     state.reset = Button('reset planner', onPlannerReset)
 
@@ -38,7 +38,7 @@ function Planner() {
 
     // should be grn / red button ... 
     state.isRunning = 1
-    state.onChange('isRunning', netStateRefresh)
+    state.onUiChange('isRunning', netStateRefresh)
 
     state.netWindow = 3
     state.netState = [0, 0, 0]
diff --git a/modules/ui/number.js b/modules/ui/number.js
index c0c17a1..08302e1 100644
--- a/modules/ui/number.js
+++ b/modules/ui/number.js
@@ -25,7 +25,7 @@ function uiNum() {
     var state = uinum.state 
 
     state.number = 10
-    state.onChange('number', onNumberDesire)
+    state.onUiChange('number', onNumberDesire)
 
     state.button = Button('WHAM', onNumberDesire)
 
diff --git a/modules/ui/stest.js b/modules/ui/stest.js
index 657e257..4f43d49 100644
--- a/modules/ui/stest.js
+++ b/modules/ui/stest.js
@@ -50,6 +50,10 @@ function STest() {
 	var ui = stest.ui 
 	ui.addElement('btnex', './ui/uiButton.js', onButtonData)
 
+	ui.btnex.onload = function(){
+		console.log('ok, yes, loaded')
+	}
+
 	function onButtonData(evt){
 		console.log('on module callback', evt)
 		ui.btnex.setText('hello from ss')
diff --git a/modules/ui/terminal.js b/modules/ui/terminal.js
index c153aa9..d6376c9 100644
--- a/modules/ui/terminal.js
+++ b/modules/ui/terminal.js
@@ -29,7 +29,7 @@ function Terminal() {
     // we'll occasionally want a hook here to do stuff when a state variable is changed
     // these will fire if we change them internally, or if they're changed from the ui
     
-    terminal.state.onChange('uiInput', function(){
+    terminal.state.onUiChange('uiInput', function(){
         terminal.outputs.lineOut.emit(terminal.state.uiInput)
     })
     
diff --git a/modules/util/delay.js b/modules/util/delay.js
index b20c87c..6f45292 100644
--- a/modules/util/delay.js
+++ b/modules/util/delay.js
@@ -21,7 +21,7 @@ function Delay() {
     var state = delay.state
 
     state.ms = 100
-    state.onChange('ms', onMsChange)
+    state.onUiChange('ms', onMsChange)
 
     delay.inputs = {
         thru: Input('any', onDelayBegin) // makes anything into '1' event
diff --git a/programs.js b/programs.js
index 97121d8..2478362 100644
--- a/programs.js
+++ b/programs.js
@@ -23,7 +23,15 @@ function loadModuleFromSource(program, path, id) {
     // source -> heap
     if (fs.existsSync(path)) {
         // compile a new object based on definition in path
-        var src = require(path)
+        var src = {}
+        try {
+            src = require(path)
+        }
+        catch(err){
+            console.log('ERR on module load, at path', path, err)
+            return false 
+        }
+        
         var mod = new src()
 
         // wants unique module id's 
diff --git a/src/atkunit.js b/src/atkunit.js
index 529bc8b..b3b355b 100644
--- a/src/atkunit.js
+++ b/src/atkunit.js
@@ -7,6 +7,10 @@ let Output = JSUnit.Output
 let State = JSUnit.State
 let Button = JSUnit.Button
 
+// interface elements
+const JSUI = require('./jsui.js')
+let UI = JSUI.UI 
+
 let ATKRoute = require('./atkroute.js')
 
 function Hardware(){
@@ -22,13 +26,23 @@ function Hardware(){
 	hardware.state = State()
 	var state = hardware.state 
 
-	state.reset = Button('reset hardware', onReset)
-
-	state.test = Button('test network', onNetworkTest)
-	state.message = 'click above to test network'
+	state.message = 'click below to test network'
 	state.route = '0,0' // default  
 
-	state.onChange('route', function(){
+	hardware.ui = UI() 
+    var ui = hardware.ui 
+
+    ui.addElement('resetButton', './ui/uiButton.js', onReset)
+    ui.resetButton.onload = function(){
+        ui.resetButton.setText('reset hardware')
+    }
+
+    ui.addElement('testButton', './ui/uiButton.js', onNetworkTest)
+    ui.testButton.onload = function(){
+        ui.testButton.setText('test network')
+    }
+
+	state.onUiChange('route', function(){
 		hardware.route.route = state.route 
 	})
 
diff --git a/src/jsunit.js b/src/jsunit.js
index 90cbec4..f1e4f2d 100644
--- a/src/jsunit.js
+++ b/src/jsunit.js
@@ -77,7 +77,7 @@ function State() {
     state.socket = null
 
     // called when change from UI 
-    state.onUIChange = function(item, fn) {
+    state.onUiChange = function(item, fn) {
         this.emitters[item] = fn
     }
 
diff --git a/src/ui/uiButton.js b/src/ui/uiButton.js
index b47a50d..576a3d5 100644
--- a/src/ui/uiButton.js
+++ b/src/ui/uiButton.js
@@ -7,17 +7,24 @@ function UIButton() {
         isPressed: false
     }
 
+    // hook to recv messages from the ui counterpart
     uiButton.onMessage = function(msg) {
         console.log('message into server side object', msg)
-        this.callback(msg)
+        if(msg == 'onload'){
+        	this.onload() 
+        } else {
+        	this.callback(msg)
+        }
     }
 
+    // example of a function to use within the module 
     uiButton.setText = function(text) {
         // ex. of how to send data up to client 
         var msg = {
             call: 'setText',
             argument: text
         }
+        // this.sendToUi is given to us during load
         this.sendToUi(msg)
     }
 
-- 
GitLab