123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- /*
- Bluetooth
- */
- function ab2str(buf) {
- return String.fromCharCode.apply(null, new Uint8Array(buf));
- }
- function str2ab(str) {
- var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
- var bufView = new Uint16Array(buf);
- for (var i=0, strLen=str.length; i<strLen; i++) {
- bufView[i] = str.charCodeAt(i);
- }
- return buf;
- }
- var receive_buffer = "";
- var received_log = "";
- var disconnect_timer;
- var legacy = true;
- var slider_pistrt ;
- function onReceiveTimeout() {
- //mecoffee_disconnect();
- mecoffee_start();
- disconnect_timer = null;
- }
- var onReceive = function(receiveInfo) {
- receive_buffer += ab2str( receiveInfo.data );
- var pos = 0, p = 0, i =0 ;
- while( ( p = receive_buffer.indexOf("\n") ) > 0 ) {
- line = receive_buffer.substring( 0, p - 1 );
- // console.log( line );
- receive_buffer = receive_buffer.substring( p + 1, receive_buffer.length );
- // Keep all received lines in a variable
- // received_log.concat( line + "\r\n" );
- mecoffee_terminal( line );
- i++;
- if( i > 25 )
- break;
- }
- // Disconnect timer
- if( disconnect_timer )
- clearTimeout( disconnect_timer );
- disconnect_timer = setTimeout( onReceiveTimeout, 5000 );
- };
- var onConnectedCallback = function() {
- if (chrome.runtime.lastError)
- console.log("Connection failed: " + chrome.runtime.lastError.message);
- //else
- //chrome.bluetoothSocket.onReceive.addListener( onReceive );
- };
- chrome.bluetoothSocket.onReceive.addListener( onReceive );
- var mecoffee_socketId;
- function mecoffee_connect( device_name ) {
- var device;
- chrome.bluetooth.getDevices(function(devices) {
-
- for (var i = 0; i < devices.length; i++) {
- if( devices[i].name == device_name ) {
- console.log(devices[i].name);
- device = devices[i];
- var uuid = '1106';
- uuid= "00001101-0000-1000-8000-00805F9B34FB";
- chrome.bluetoothSocket.create( function(createInfo) {
- mecoffee_socketId = createInfo.socketId;
- chrome.bluetoothSocket.connect(createInfo.socketId,
- device.address, uuid, onConnectedCallback);
- chrome.bluetoothSocket.onAcceptError.addListener( function() { console.log('onaccepterror'); } );
- chrome.bluetoothSocket.onReceiveError.addListener( function() { console.log('onreceiveerror'); } );
- chrome.runtime.sendMessage( { type: 'socket', socket: mecoffee_socketId }, function(response) { console.log( 'socket antwoord' ); } );
- });
- break;
- }
- }
- });
- }
- function mecoffee_disconnect( ) {
- chrome.bluetoothSocket.disconnect( mecoffee_socketId );
- chrome.bluetoothSocket.close( mecoffee_socketId );
- mecoffee_timestamp_start = null;
- }
- function mecoffee_bt_enum_devices( ) {
- if( !chrome || !chrome.bluetooth )
- return ;
- chrome.bluetooth.getDevices(function(devices) {
-
- $('#device option[value="none"]').remove()
- for (var i = 0; i < devices.length; i++) {
- $('#devices').append('<option value="device_' + devices[i].name + '">' + devices[i].name + '</option>');
- }
- $('#device')[0].selectedIndex = 0;
- $('#device').selectpicker("refresh")
- });
- }
- /*
- meCoffee protocol
- */
- var mecoffee_timestamp_start;
- function mecoffee_terminal_tmp( items ) {
- var ts = parseInt( items[1] );
- var tmp = parseInt( items[3] ) / 100;
- var tmp2 = parseInt( items[4] ) / 100;
- var tmpsp = parseInt( items[2] ) / 100;
- if( !mecoffee_timestamp_start && mecoffee_timestamp_start != 0 ) {
- mecoffee_timestamp_start = ts ;
- mecoffee_terminal_write( "\r\ncmd dump OK\r\n" );
- }
- if( ts - mecoffee_timestamp_start == 2 ) {
- var d = new Date(), e = new Date(d);
- var msSinceMidnight = e - d.setHours(0,0,0,0);
- mecoffee_terminal_write( "\r\ncmd clock set " + parseInt( msSinceMidnight / 1000 ) + " OK\r\n" );
- console.log( 'clock set to ' + parseInt( msSinceMidnight / 1000 ) );
- }
- if( ts - mecoffee_timestamp_start == 5 ) {
-
- mecoffee_terminal_write( "\r\ncmd uname OK\r\n");
-
- }
-
- graph.tick( tmp, tmp2, tmpsp, ts - mecoffee_timestamp_start );
- //mecoffee_cur_tmp = tmp;
- //mecoffee_cur_sp = tmpsp;
- document.querySelector('#mc_tmp').value = tmp;
- document.querySelector('#mc_tmpsp').value = tmpsp;
- }
- var gauge_boiler;
- function mecoffee_terminal_pid( items ) {
- var pid = parseInt( items[1] ) + parseInt( items[2] ) + parseInt( items[3] );
- gauge_boiler.write( pid / 65536 * 100);
- }
- var gauge_shottimer;
- var gauge_shottimer_time;
- var gauge_shottimer_timeout;
- var gauge_shottimer_interval = null;
- function mecoffee_terminal_shot( items ) {
- var value = parseInt( items[ items.length - 2 ] );
- var speed = 1;
- if( mecoffee_demo_interval > 0 ) {
- speed = $('#demo_speed')[0].value;
- }
- if( gauge_shottimer_timeout ) {
- clearTimeout( gauge_shottimer_timeout );
- gauge_shottimer_timeout = null;
- }
- $('#gauge_shottimer').show();
- // start interval to update shot timer every sec
- if( value == 0 && gauge_shottimer_interval == null ) {
- gauge_shottimer_time = 0;
- console.log( 'started interval ' );
- gauge_shottimer_interval = setInterval( function() {
- gauge_shottimer.write( ++gauge_shottimer_time );
- //console.log( 'update shot timer to ' + gauge_shottimer_time );
- },
- 1000 / speed );
- }
- // clean up shot timer after 30 secs
- if( value > 0 ) {
- if( gauge_shottimer_interval ) {
- clearInterval( gauge_shottimer_interval );
- gauge_shottimer_interval = null;
- gauge_shottimer.write( value / 1000.0 );
- }
- gauge_shottimer_timeout = setTimeout( function() {
- gauge_shottimer.write( 0 );
- $('#gauge_shottimer').hide();
- gauge_shottimer_timeout = null;
- },
- Math.min( 30000, 30000 / speed )
- );
- }
- gauge_shottimer.write( value / 1000 );
- }
- function mecoffee_terminal_cmd( items ) {
-
- if( items[1] == 'get' ) {
- var elems = $( '#mc_' + items[2] );
- var value = items[3];
-
- if( elems.length == 0 ) {
- console.log( '#mc_' + items[2] + ' not found' );
- return;
- }
- var elem = elems[0];
- var scale = elem.getAttribute('data-scale');
- if( scale )
- value /= scale;
- if( elems[0].className.indexOf('timepicker') >= 0) {
- var hour = Math.floor( value / ( 60*60 ) );
- var min = value % ( 60*60 );
- elems[0].value = hour + ':' + Math.floor( min / 60 );
- return;
- }
- if( elems[0].type == "checkbox" ) {
- elems.bootstrapSwitch('state' , items[3] == "1" );
- return;
- }
- if( elems.attr( 'data-slider-value' ) ) {
- elems.slider( 'setValue', parseInt( items[3] ) );
- return;
- }
- elems[0].value = value;
- }
- }
- function mecoffee_terminal_uname( line ) {
-
- legacy = line.indexOf( 'V4' ) > 0;
- if( legacy ) {
- console.log( 'meCoffee is legacy ( V4 )' );
- $('#mc_pistrt')[0].setAttribute( 'data-scale', 1 );
- $('#mc_pistrt')[0].setAttribute( 'data-slider-step', 1 );
- $('#mc_pistrt').slider( 'destroy' );
- $('#mc_pistrt').slider( );
- $( '#mc_pistrt' ).change( mecoffee_control_change );
-
- $('#mc_piprd')[0].setAttribute( 'data-scale', 1 );
- $('#mc_piprd')[0].setAttribute( 'data-slider-step', 1 );
- $('#mc_piprd').slider( 'destroy' );
- $('#mc_piprd').slider( );
- $( '#mc_piprd' ).change( mecoffee_control_change );
- }
- else {
- console.log( 'meCoffee has newish firmware' );
-
- $('#mc_pistrt')[0].setAttribute( 'data-scale', 1000 );
- $('#mc_pistrt')[0].setAttribute( 'data-slider-step', "0.1" );
- $('#mc_pistrt').slider( 'destroy' );
- $('#mc_pistrt').slider( );
- $( '#mc_pistrt' ).change( mecoffee_control_change );
- $('#mc_piprd')[0].setAttribute( 'data-scale', 1000 );
- $('#mc_piprd')[0].setAttribute( 'data-slider-step', 0.1 );
- $('#mc_piprd').slider( 'destroy' );
- $('#mc_piprd').slider( );
- $( '#mc_piprd' ).change( mecoffee_control_change );
- }
- // $('.slider').destroy();
- // $('.slider').slider();
- // $('#mc_pistrt')[0].setAttribute( 'data-scala', 1000 );
- }
- function mecoffee_terminal( line ) {
- received_log = received_log.concat( line + "\n" );
-
- var items = line.split(' ');
- if( items[ items.length - 1 ] != 'OK' )
- return;
- if( items[0] == 'tmp' ) {
- mecoffee_terminal_tmp( items );
- }
- if( items[1] == 'uname' ) {
- mecoffee_terminal_uname( line );
- return;
- }
- if( items[0] == 'cmd' )
- mecoffee_terminal_cmd( items );
- if( items[0] == 'pid' )
- mecoffee_terminal_pid( items );
- if( items[0] == 'sht' )
- mecoffee_terminal_shot( items );
- }
- function mecoffee_terminal_write( line ) {
- if( !mecoffee_socketId )
- return ;
- chrome.bluetoothSocket.send( mecoffee_socketId, str2ab( line ), function(bytes_sent) {
-
- if (chrome.runtime.lastError) {
- console.log("Send failed: " + chrome.runtime.lastError.message);
- } else {
- console.log("Sent " + bytes_sent + " bytes")
- }
- });
- }
- /*
- Demo
- */
- var mecoffee_demo_log = "";
- var mecoffee_demo_interval = 0;
- var mecoffee_demo_cnt = 0;
- function mecoffee_demo_timer( ) {
- if( mecoffee_demo_cnt >= mecoffee_demo_log.length ) {
-
- mecoffee_demo_stop();
- //clearInterval( mecoffee_demo_interval );
- // TODO: change start button state
-
- //mecoffee_demo_cnt = 0;
- }
- for( ; mecoffee_demo_cnt < mecoffee_demo_log.length ; mecoffee_demo_cnt++ ) {
- var line = mecoffee_demo_log[mecoffee_demo_cnt];
- mecoffee_terminal( line );
- if( line.indexOf('tmp ') == 0 ) {
- mecoffee_demo_cnt++;
- break;
- }
- }
- }
- function mecoffee_demo( log ) {
- log = log.replace( "share_", "" );
- $.get( "https://mecoffee.nl/share/logs/" + log, function( data ) {
- mecoffee_demo_log = data.split("\n");
-
- mecoffee_demo_interval = setInterval( mecoffee_demo_timer, 1000 / $('#demo_speed')[0].value );
- });
-
- return false;
- }
- function mecoffee_demo_speed( e ) {
- if( !mecoffee_demo_interval )
- return ;
- clearInterval( mecoffee_demo_interval );
- mecoffee_demo_interval = setInterval( mecoffee_demo_timer, 1000 / e.target.value );
- }
- function mecoffee_demo_stop( e ) {
- if( mecoffee_demo_interval )
- clearInterval( mecoffee_demo_interval );
- mecoffee_demo_interval = 0;
- mecoffee_demo_cnt = 0;
- $('#start_icon')[0].className = "glyphicon glyphicon-play";
- $('#start_label')[0].innerHTML = "Start";
- start.className ="btn btn-primary";
- }
- /*
- App
- */
- function mecoffee_start( e ) {
- var start = $('#start')[0];
- if( start.className.indexOf("danger") > 0 ) {
- // Stop
- start.className ="btn btn-primary";
- $('#start_icon')[0].className = "glyphicon glyphicon-play";
- $('#start_label')[0].innerHTML = "Start";
- mecoffee_disconnect( );
- mecoffee_demo_stop( );
- }
- else {
- // Start
- start.className ="btn btn-danger";
- $('#start_icon')[0].className = "glyphicon glyphicon-stop";
- $('#start_label')[0].innerHTML = "Stop";
- var value = $('#device')[0].value;
- if( value.indexOf('device_') == 0 )
- mecoffee_connect( value.replace( 'device_', '' ) );
- if( value.indexOf('share_') == 0 )
- mecoffee_demo( value );
- }
- return false;
- }
- function mecoffee_share( e ) {
- $.post( "https://mecoffee.nl/share/post.php", { logfile: received_log }, function( data ) {
- $( "#share_result" ).html( '<a target="_blank" href=""' + data + '">' + data + '</a>');
- window.open( data, "_blank" );
- });
- return false;
- }
- function mecoffee_control_change( e ) {
- var elem = e.target;
- if( elem.id.indexOf('mc_') != 0 )
- return;
- var value = elem.value;
- if( e.value && e.value.newValue )
- value = e.value.newValue;
- if( elem.type == "checkbox" )
- value = elem.checked ? 1 : 0;
- if( value.indexOf && value.indexOf(':') > 0 ) {
- var p = value.split(':');
- value = 60*60*p[0] + 60*p[1];
- }
- var scale = elem.getAttribute('data-scale');
- if( scale )
- value *= scale;
-
- var line = "\r\ncmd set " + elem.id.replace( "mc_", "" ) + " " + value + " OK\r\n";
-
- console.log( line );
- mecoffee_terminal_write( line );
- }
- var graph;
- function mecoffee_app_startup() {
- //document.querySelector("#doit").addEventListener( 'click', doit_doit );
- $('#start').click( mecoffee_start );
- $('#share').click( mecoffee_share );
- window.addEventListener("resize", function() { graph.draw(); });
- graph = new meCoffeeGraph(); graph.draw();
- $("input[type='checkbox']").bootstrapSwitch( { onSwitchChange: function ( e ) { mecoffee_control_change( e ); }});
- // slider_pistrt = new Slider( '#mc_pistrt' );
- $('.slider').slider();
- $('.timepicker').timepicker( { showMeridian: false } );
- $( ".target" ).change( mecoffee_control_change );
- $( "#demo_speed").change( mecoffee_demo_speed );
- //var
- gauge_boiler = new Gauge();
- gauge_boiler.draw( $('#gauge_boiler')[0] , { label: 'Boiler %' } );
- gauge_shottimer = new Gauge();
- gauge_shottimer.draw( $('#gauge_shottimer')[0] , { label: 'Shot (s)', max: 30 } );
- mecoffee_bt_enum_devices( );
- }
- window.addEventListener("DOMContentLoaded", mecoffee_app_startup );
-
|