1
1
var gpio = require ( "gpio" ) ;
2
2
gpio . logging = true ;
3
3
4
- var gpioID = 4 ; //actually pin 7, 4 down on left header
5
- var gpioDevice ;
6
- var connected = false ; //ensure only one process talks to us at a time.
4
+
5
+ // The gpio ids we're using. Note that these aren't the pin numbers, but
6
+ // the IDs exposed by the Pi. Search for Pi GPIO pinout for details.
7
+ var ledGPIOID = 4 ; //actually pin 7, 4 down on left header
8
+ var buttonGPIOID = 17 ;
9
+
10
+ // Handles for our connected gpio devices
11
+ var ledDevice ;
12
+ var buttonDevice ;
13
+
14
+ // A collection of all connected sockets.
15
+ // Maps socketid => { socket: sockethandle, id: socketid }
16
+ var connections = { } ;
7
17
8
18
exports . settings = { } ;
9
19
//These are dynamically updated by the runtime
@@ -15,89 +25,66 @@ exports.settings={};
15
25
//settings.coder_owner - name of the user, Ie. "Suzie Q."
16
26
//settings.coder_color - hex css color given to this coder.
17
27
28
+ // Incoming get routes that our app knows how to respond to
18
29
exports . get_routes = [
19
- { path :'/' , handler :'index_handler' } ,
30
+ { path :'/' , handler :'index_handler' } , // Render out main html page
20
31
] ;
21
32
33
+ // Incoming post routes that our app knows how to respond to
34
+ // (None in this example)
22
35
exports . post_routes = [
23
36
] ;
24
37
38
+ // Incoming socket events that this module will expose.
25
39
exports . socketio_routes = [
26
- { key :'connect' , handler :'on_socket_connect' } ,
27
- { key :'gpio ' , handler :'on_socket_gpio ' } ,
40
+ { key :'connect' , handler :'on_socket_connect' } , // sent by client once socket is loaded
41
+ { key :'setled ' , handler :'on_socket_setled ' } , // sent by client to turn on/off the led
28
42
] ;
29
43
30
44
31
- var connections = { } ;
32
45
46
+ //
47
+ // Handles sending the HTML page to the browser
48
+ //
33
49
exports . index_handler = function ( req , res ) {
50
+ // Set up some template variables that are substituted in our HTML.
51
+ // Look in the HTML head tag to see where these are inserted.
34
52
var tmplvars = { } ;
35
53
tmplvars [ 'static_url' ] = exports . settings . staticurl ;
36
54
tmplvars [ 'app_name' ] = exports . settings . appname ;
37
55
tmplvars [ 'app_url' ] = exports . settings . appurl ;
38
56
tmplvars [ 'device_name' ] = exports . settings . device_name ;
39
57
58
+ // Send the HTML document to the web browser.
40
59
res . render ( exports . settings . viewpath + '/index' , tmplvars ) ;
41
60
} ;
42
61
43
62
44
- var enableGPIO = function ( ) {
45
- console . log ( "Enabling GPIO " + gpioID ) ;
46
- gpioDevice = gpio . export ( gpioID , {
47
- ready : function ( ) {
48
- //Pause briefly after pin is exported.
49
- //There seems to be an error if you try to immediately access it.
50
- setTimeout ( function ( ) {
51
- console . log ( "GPIO value: on" ) ;
52
- gpioDevice . setDirection ( "out" ) ;
53
- gpioDevice . set ( 1 , function ( ) {
54
- console . log ( "GPIO should be on" ) ;
55
- } ) ;
56
- //blinkLED();
57
- } , 100 ) ;
58
- }
59
- } ) ;
60
- } ;
61
- var disableGPIO = function ( ) {
62
- console . log ( "Disabling GPIO" + gpioID ) ;
63
- gpioDevice . removeAllListeners ( ) ;
64
- gpioDevice . reset ( ) ;
65
- gpioDevice . unexport ( ) ;
66
- } ;
67
-
68
- var ledval = 0 ;
69
- var blinkLED = function ( ) {
70
- if ( ! connected ) {
71
- return ;
72
- }
73
-
74
- gpioDevice . set ( ledval ) ;
75
- if ( ledval == 0 ) {
76
- ledval = 1 ;
77
- } else {
78
- ledval = 0 ;
79
- }
80
-
81
- //run this method again after half a second
82
- setTimeout ( blinkLED , 500 ) ;
83
- } ;
84
-
85
-
86
-
63
+ //
64
+ // Respond to the "connect" message sent by a new socket client.
65
+ //
66
+ // We do two things here:
67
+ // 1. save the socket object into the "connections" variable so we can talk to it later.
68
+ // 2. initialize the GPIO pins if this is the first time a socket has connected.
69
+ //
87
70
exports . on_socket_connect = function ( socket , data ) {
88
71
console . log ( 'socket connect from ID: ' + socket . socketID ) ;
89
72
console . log ( data ) ;
90
73
91
- if ( ! connected ) {
74
+ // Enable the GPIO pins if this is the first connection
75
+ if ( Object . keys ( connections ) . length <= 0 ) {
92
76
enableGPIO ( ) ;
93
- connected = true ;
94
77
}
95
78
79
+ // Store information about this socket so we can communicate with
80
+ // all connected sockets in the future.
96
81
connections [ socket . socketID ] = {
97
82
socket : socket ,
98
- name : data . name ,
99
83
id : socket . socketID
100
84
} ;
85
+
86
+ // Watch for this socket to disconnect so that we can remove it from
87
+ // our collection of connected sockets.
101
88
socket . on ( 'disconnect' , function ( ) {
102
89
console . log ( 'socket disconnect from ID: ' + socket . socketID ) ;
103
90
delete connections [ socket . socketID ] ;
@@ -111,41 +98,113 @@ exports.on_socket_connect = function( socket, data ) {
111
98
112
99
} ;
113
100
101
+ //
102
+ // Respond to a "setled" message from a socket connection to update the LED value
103
+ //
104
+ exports . on_socket_setled = function ( socket , data ) {
105
+ if ( data . value !== "undefined" ) {
106
+ setLED ( data . value ) ;
107
+ }
108
+ } ;
109
+
110
+
111
+
112
+ //
113
+ // This is called once from our first socket connection.
114
+ // - set up the LED GPIO as an output
115
+ // - set up the Button GPIO as an input and tie it to send a "change" message
116
+ //
117
+ var enableGPIO = function ( ) {
118
+
119
+ // Set up the LED output GPIO
120
+ console . log ( "Setting up LED as an output on GPIO " + ledGPIOID ) ;
121
+ ledDevice = gpio . export ( ledGPIOID , {
122
+ direction : "out" ,
123
+ ready : function ( ) {
124
+ }
125
+ } ) ;
126
+
127
+ // Set up the button input GPIO
128
+ console . log ( "Setting up Button as an input on GPIO" + buttonGPIOID ) ;
129
+ buttonDevice = gpio . export ( buttonGPIOID , {
130
+ direction : "in" ,
131
+ ready : function ( ) {
132
+
133
+ // Set up buttonDevice to call the buttonChange
134
+ // function (below) whenever its value changes.
135
+ buttonDevice . on ( "change" , buttonChange ) ;
136
+ }
137
+ } ) ;
138
+
139
+ } ;
140
+
141
+ //
142
+ // This is called when the last socket disconnects.
143
+ // It releases our GPIO pins so they can be used by another program.
144
+ //
145
+ var disableGPIO = function ( ) {
146
+ console . log ( "Disabling GPIO" + ledGPIOID ) ;
147
+ ledDevice . removeAllListeners ( ) ;
148
+ ledDevice . reset ( ) ;
149
+ ledDevice . unexport ( ) ;
150
+
151
+ console . log ( "Disabling GPIO" + buttonGPIOID ) ;
152
+ buttonDevice . removeAllListeners ( ) ;
153
+ buttonDevice . reset ( ) ;
154
+ buttonDevice . unexport ( ) ;
155
+ } ;
114
156
115
- exports . on_socket_gpio = function ( socket , data ) {
116
- switch ( data . command ) {
117
- case "set" :
118
- setGPIO ( data . value ) ;
119
- break ;
120
- case "direction" :
121
- setDirection ( data . direction ) ;
122
- break ;
123
- case "value" :
124
- sendValue ( socket ) ;
125
- break ;
157
+ //
158
+ // This is triggered by the GPIO "change" event on buttonDevice. This was
159
+ // set up inside emabledGPIO().
160
+ //
161
+ // The change event sends this function a value, either 0 (off) or 1 (on).
162
+ //
163
+ var buttonChange = function ( val ) {
164
+ // Recall that this code is running on the device. We need to send a
165
+ // socket message with the button data to our javascript in the
166
+ // web browser. In fact, we need to send this data to every connected
167
+ // socket, since there may be more than one browser window looking at
168
+ // this page.
169
+
170
+ console . log ( "buttonChange event with value: " + val ) ;
171
+
172
+ // Iterate through all of our socket connections
173
+ for ( var socketid in connections ) {
174
+ // Get the socket object for this socket
175
+ var socket = connections [ socketid ] . socket ;
176
+
177
+ // The "appdata" event will be received by the Coder.socketConnection
178
+ // object in the front end code and sent to the appropriate listener
179
+ // that we've defined.
180
+ // The "buttonupdate" key refers to a listener we set up on the front
181
+ // end with the code:
182
+ // Coder.socketConnection.addListener( "buttonupdate", function... )
183
+ socket . emit ( "appdata" , {
184
+ key : "buttonupdate" ,
185
+ data : val
186
+ } ) ;
126
187
}
127
188
} ;
128
189
129
- var setGPIO = function ( val ) {
190
+ //
191
+ // Set the value on the LED GPIO device, either 0 (off) or 1 (on).
192
+ //
193
+ var setLED = function ( val ) {
130
194
val = parseInt ( val ) ;
131
195
if ( val != 0 ) {
132
196
val = 1 ;
133
197
}
134
- gpioDevice . set ( val ) ;
135
- } ;
136
- var setDirection = function ( dir ) {
137
- if ( dir !== "in" ) {
138
- dir = "out" ;
139
- }
140
- gpioDevice . setDirection ( dir ) ;
141
- } ;
142
- var sendValue = function ( socket ) {
143
- socket . emit ( "apdata" , {
144
- key : "gpiovalue" ,
145
- data : gpioDevice . value
146
- } ) ;
198
+ ledDevice . set ( val ) ;
147
199
} ;
148
200
201
+ //
202
+ // Called by Coder whenever this module is reloaded. This usually happens when
203
+ // you save your code in the editor. This is a good place to destroy any intervals
204
+ // or clean up any long running code or handles.
205
+ //
149
206
exports . on_destroy = function ( ) {
150
207
} ;
151
208
209
+
210
+
0 commit comments