@@ -65,7 +65,7 @@ module.exports = [
6565 function ( $window , $location , $rootScope , alertService ) {
6666 $rootScope . $on ( '$routeChangeStart' , function ( ) {
6767 angular . element ( $window ) . unbind ( 'message' ) ;
68- clearInterval ( $rootScope . serialInterval ) ;
68+ clearTimeout ( $rootScope . serialTimeout ) ;
6969 } ) ;
7070
7171 return {
@@ -74,64 +74,116 @@ module.exports = [
7474 angular . element ( $window ) . bind ( 'message' , function ( e ) {
7575 cb ( e . data ) ;
7676 } ) ;
77+ if ( $window . location . href . includes ( 'dummyReader' ) ) {
78+ $rootScope . dummyReader = true ;
79+ $window . scanCard = ( cardKey ) =>
80+ $window . window . postMessage ( cardKey , '*' ) ;
81+
82+ $window . console . error ( `VOTE DUMMY READER MODE
83+
84+ You are now in dummy reader mode of VOTE. Use the global function "scanCard" to scan a card. The function takes the card UID as the first (and only) parameter, and the UID can be both a string or a number.
85+
86+ Usage: scanCard(123) // where 123 is the cardId ` ) ;
87+ }
7788 // Open serial connections if they are not already open
78- if ( ! $rootScope . serialWriter || ! $rootScope . serialReader ) {
89+ if (
90+ ! $rootScope . serialDevice &&
91+ ! $rootScope . ndef &&
92+ ! $rootScope . dummyReader
93+ ) {
7994 try {
80- const port = await $window . navigator . serial . requestPort ( { } ) ;
81-
82- await port . open ( { baudRate : 9600 } ) ;
83- $rootScope . serialWriter = port . writable . getWriter ( ) ;
84- $rootScope . serialReader = port . readable . getReader ( ) ;
95+ if (
96+ $window . navigator . userAgent . includes ( 'Android' ) &&
97+ $window . NDEFReader &&
98+ ( ! $window . navigator . serial ||
99+ $window . confirm (
100+ 'You are using an Android device that (might) support web nfc. Click OK to use web nfc, and cancel to fallback to using a usb serial device.'
101+ ) )
102+ ) {
103+ const ndef = new $window . NDEFReader ( ) ;
104+ await ndef . scan ( ) ;
105+ $rootScope . ndef = ndef ;
106+ } else {
107+ const port = await $window . navigator . serial . requestPort ( { } ) ;
108+ await port . open ( { baudRate : 9600 } ) ;
109+ $rootScope . serialDevice = {
110+ writer : port . writable . getWriter ( ) ,
111+ reader : port . readable . getReader ( ) ,
112+ } ;
113+ }
85114 } catch ( e ) {
86115 $rootScope . $apply ( ( ) => {
87116 $location . path ( '/moderator/serial_error' ) ;
88117 } ) ;
89118 }
90119 }
91- if ( ! $rootScope . serialWriter || ! $rootScope . serialReader ) {
92- return ;
93- }
94-
95- let lastTime = 0 ;
96- let lastData = 0 ;
97- const onComplete = ( input ) => {
98- const { valid, status, data } = parseData ( input ) ;
99- if ( valid && status == 'OK' ) {
100- // Debounce
101- if ( data !== lastData || Date . now ( ) - lastTime > 2000 ) {
102- // data = card id
103- cb ( data ) ;
104- lastTime = Date . now ( ) ;
105- lastData = data ;
120+ if ( $rootScope . ndef ) {
121+ $rootScope . ndef . onreading = ( { message, serialNumber } ) => {
122+ const data = convertUID ( serialNumber . split ( ':' ) ) ;
123+ cb ( data ) ;
124+ } ;
125+ } else if ( $rootScope . serialDevice ) {
126+ let lastTime = 0 ;
127+ let lastData = 0 ;
128+ const onComplete = ( input ) => {
129+ const { valid, status, data } = parseData ( input ) ;
130+ if ( valid && status == 'OK' ) {
131+ // Debounce
132+ if ( data !== lastData || Date . now ( ) - lastTime > 2000 ) {
133+ // data = card id
134+ cb ( data ) ;
135+ lastTime = Date . now ( ) ;
136+ lastData = data ;
137+ }
106138 }
107- }
108- } ;
139+ } ;
140+ const readResult = async ( ) => {
141+ const message = [ ] ;
142+ let finished = false ;
143+ // Keep reading bytes until the "end" byte is sent
144+ // The "end" byte is 0xbb
145+ while ( ! finished ) {
146+ const { value } = await $rootScope . serialDevice . reader . read ( ) ;
147+ for ( let i = 0 ; i < value . length ; i ++ ) {
148+ // First byte in a message should be 170, otherwise ignore and keep on going
149+ if ( message . length === 0 && value [ i ] !== 170 ) {
150+ continue ;
151+ }
152+ // Second byte in a message should be 255, otherwise discard and keep on going
153+ if ( message . length === 1 && value [ i ] !== 255 ) {
154+ // If value is 170, treat it as the first value, and keep on. Otherwise discard
155+ if ( value [ i ] !== 170 ) {
156+ message . length = 0 ;
157+ }
158+ continue ;
159+ }
109160
110- const readResult = async ( ) => {
111- const message = [ ] ;
112- let finished = false ;
113- // Keep reading bytes until the "end" byte is sent
114- // The "end" byte is 0xbb
115- while ( ! finished ) {
116- const { value } = await $rootScope . serialReader . read ( ) ;
117- for ( let i = 0 ; i < value . length ; i ++ ) {
118- if ( value [ i ] == 0xbb ) {
119- finished = true ;
120- break ;
161+ if ( message . length > 3 && message . length >= message [ 2 ] + 4 ) {
162+ finished = true ;
163+ break ;
164+ }
165+ message . push ( value [ i ] ) ;
121166 }
122- message . push ( value [ i ] ) ;
123167 }
124- }
125- onComplete ( message ) ;
126- } ;
168+ onComplete ( message ) ;
169+ } ;
127170
128- // Constantly send the readCardCommand and read the result.
129- // If there is no card, the result will be an error status,
130- // which is handled in the onComplete function
131- $rootScope . serialInterval = setInterval ( ( ) => {
132- $rootScope . serialWriter . write ( readCardCommand ) ;
133- readResult ( ) ;
134- } , 500 ) ;
171+ // Constantly send the readCardCommand and read the result.
172+ // If there is no card, the result will be an error status,
173+ // which is handled in the onComplete function
174+ const runPoll = async ( ) => {
175+ try {
176+ $rootScope . serialDevice . writer . write ( readCardCommand ) ;
177+ await readResult ( ) ;
178+ } catch ( e ) {
179+ /* eslint no-console: 0 */
180+ console . error ( 'Error doing card stuff' , e ) ;
181+ } finally {
182+ $rootScope . serialTimeout = setTimeout ( runPoll , 150 ) ;
183+ }
184+ } ;
185+ runPoll ( ) ;
186+ }
135187 } ,
136188 } ;
137189 } ,
0 commit comments