JavaScript Coffee Maker
Overview
This JavaScript example is intended to show you how to implement a real application using the NearBus system. The example is based in coffee machine system which has a good level of complexity to understand how the NearBus system works. (edit the .html file to see the code explanation). The example shows how control different devices (motors, sensors, etc.) using the NearBus RESTful API.
The following picture details how each element can be controlled through a simple URL, simplifying the HW integration in any SW deployment platform (JavaScript, Java, PHP, etc.)
JavaScript Code
Note: In order to run this example you should download and run the CoffeMaker_1v0.html javascript file inside the folder.
Donwload: http://www.nearbus.net/downloads/js_apps/CoffeMaker_1v0.rar
PROGRAM DESCRIPTION
This JavaScript example is intended to show you how to implement a real application using the NearBus system. The example is based in coffee machine system which has a good level of complexity to understand how the NearBus system works. The system works as a finite state machine that implement the sequence required to accomplish the coffee maker process.
The selected coffee machine has the following components:
- A motorized Valve (to isolate the coffee grains compartment).
- A Grinder Motor (to grind the coffee grains).
- An Electric Heater to boil the water in order to make the coffee.
There are some others sensors like Thermal switchs and Temperature sensors that are not included in this example in order to simplify the explanation.
This example uses the following NearBus API service:
NearAPI: nearbus.net/v1/api_vmcu_jsb
This implementation only works with the NearAgent version v06 (or greater).
API Characteristics:
- This API service returns immediately (with the actual value in the NearBus Data Base).
- The API needs a “request_id” in order to match the request with the response. If the "request_id" does not match with the "request_id" in the NearBus Data Base, the API return "NULL" (this means that you always will need make two requests in order to obtain a valid value (no NULL). This "twin-call" procedure allows to the API call returns immediately simplifying the way in which the system can be programmed under JavaScript.
- The main NearBIOS Service used in this example is the PULSE_OUTPUT. This service allows you to generate a pulse of x [ms] (in steps of 10ms).
- This feature allows turn on a remote power device in a secure way through Internet, because you will be sure that the remote powered device will be shut down even if the internet connection with the remote Agent is lost.
- The following REST call can be used to test the system in a manual way:
http:nearbus.net/v1/api_vmcu_jsb/NB100***?user=***&pass=***&channel=0&service=PULSE_OUTPUT&value=500&method=POST&reqid=12345
- There are another additional security features like the "Watch Dog" counter. This feature “supervise the critical sections in the state machine and resets the system if it go into a infinite (or very long) loop.
You can try this example with an Arduino Ethernet or Wi-Fi board checking the sequence over the pins 3-5-6-and 9 (arduino Uno Board)
<!DOCTYPE html> <html> <head> <script src="http://code.jquery.com/jquery-1.9.1.min.js"></script> <script type="text/javascript" src="PAGE" ></script> <script type='text/javascript' src='http://nearbus.net/downloads/js_apps/nearapi_v03.js'></script> <script> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // / | / /__ ____ ______/ /_ __ _______ // // / |/ / _ \/ __ `/ ___/ __ \/ / / / ___/ // // / /| / __/ /_/ / / / /_/ / /_/ (__ ) // // /_/ |_/\___/\__,_/_/ /_.___/\__,_/____/ // // www.nearbus.net - info@nearbus.net // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // REVISION HISTORY // v0.1 - 09-08-13 - Initial Release // v0.2 - 14-10-13 - Upgrade to support nearapi_v03.js // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // +------------------------------------------------------------------------------+ // | IMPORTANT | // | Be careful to avoid run more than one scripts simultaneously !!! | // | Don't forget CLOSE the running script before start a new or modified script. | // | The NearBus system can run multiple scripts but the system output will be | // | the mix of all running sessions. | // +------------------------------------------------------------------------------+ // +--------------------------------------------------------------------+ // | To run this example you should replace the following parameters | // | device_id Your device ID, or.. devices ID :) | // | user Your NearBus Web user | // | pass Your NearBus Web password | // +--------------------------------------------------------------------+ ////////////////////////////////// // MAIN CONFIGURATION ////////////////////////////////// var device_id = "NB100***"; // Your device ID var user = "****"; // Your NearBus Web user var pass = "****"; // Your NearBus Web password var intensity = "TEST"; // Coffee Intensity var LOOP_DELAY = 2000; // Main Loop Delay in ms var WATCH_DOG = 31; // Watch Dog TTL ////////////////////////////////// // Defines ////////////////////////////////// // ELEMENT PORT var THERMOSTAT = 1; // Bimetal Thermal Switch ( Heater sensor ) var CLOSE_VALVE = 2; // Grinder Coffee Valve (Close) var OPEN_VALVE = 3; // Grinder Coffee Valve (Open) var MOTOR_ON = 4; // Grinder Motor var HEATER_ON = 5; // Water Heater ////////////////////////////////// // Persistent Variables ////////////////////////////////// var step_pointer = 5; var reset_system; var enable_system; var ret = 0; var my_watch_dog = WATCH_DOG; var state_log = "Waiting"; var heater = "OFF"; var aux_delay = 0; /////////////////////////////////// // Function: sysStop() /////////////////////////////////// function sysStop() { reset_system = 1; enable_system = 0; } /////////////////////////////////// // Function: sysStart() /////////////////////////////////// function sysStart() { enable_system = 1; reset_system = 0; } /////////////////////////////////// // Function: refreshDisplay() /////////////////////////////////// function refreshDisplay() { $('#field_1').text( "STEP = " + step_pointer.toString() ); $('#field_2').text( "STATE = " + state_log ); $('#field_3').text( "NearAPI Ret = " + ret ); $('#field_4').text( "Watch_Dog = " + my_watch_dog.toString() ); $('#field_5').text( "Heater = " + heater ); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Function: Main /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// $(document).ready( function () { state_log = "Starting..."; setInterval( function() { //************************************************** // WATCH DOG CONTROL //************************************************** my_watch_dog--; if ( my_watch_dog <= 0 ) { my_watch_dog = WATCH_DOG; step_pointer = 5; } //************************************************** // ERROR CHECK //************************************************** if ( ret == "ERROR" ) { step_pointer = 5; } ///////////////////////////////////////////////////////////////////// // STATE MACHINE ///////////////////////////////////////////////////////////////////// if( reset_system == 1 ) { reset_system = 0; step_pointer = 5; } refreshDisplay(); switch ( step_pointer ) { ///////////////////////////////////////////////////////////////////// // [STEP 5] - SYSTEM RESET ///////////////////////////////////////////////////////////////////// case 5: state_log = "Resetting System... ( please wait )"; refreshDisplay(); ret = NearAPIjs( "DIG_OUTPUT", device_id, HEATER_ON, 0 ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 6; } break; ///////////////////////////////////////////////////////////////////// // [STEP 6] - SYSTEM OFF ///////////////////////////////////////////////////////////////////// case 6: state_log = "System READY"; refreshDisplay(); heater = "OFF"; my_watch_dog = WATCH_DOG; if( enable_system == 1 ) { enable_system = 0; step_pointer = 10; } break; ///////////////////////////////////////////////////////////////////// // [STEP 10] - RESETING VALVE (CLOSE) ///////////////////////////////////////////////////////////////////// case 10: state_log = "Resetting_Valve"; refreshDisplay(); ret = NearAPIjs( "PULSE_OUTPUT", device_id, CLOSE_VALVE, 6000 ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 15; } break; ///////////////////////////////////////////////////////////////////// // [STEP 15] - RESETING VALVE (CLOSE) ACK ///////////////////////////////////////////////////////////////////// case 15: state_log = "Waiting: Reset_Valve_ACK"; refreshDisplay(); ret = NearAPIjs( "GET_PULSE_OUTPUT", device_id, CLOSE_VALVE, 0 ); if( ret == 0 ) { my_watch_dog = WATCH_DOG; step_pointer = 20; } break; ///////////////////////////////////////////////////////////////////// // [STEP 20] - OPEN VALVE ///////////////////////////////////////////////////////////////////// case 20: state_log = "Opening_Valve"; refreshDisplay(); ret = NearAPIjs( "PULSE_OUTPUT", device_id, OPEN_VALVE, 6000 ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 25; } break; ///////////////////////////////////////////////////////////////////// // [STEP 25] - OPEN VALVE ACK (1) ///////////////////////////////////////////////////////////////////// case 25: state_log = "Waiting: Open_Valve_ACK"; refreshDisplay(); ret = NearAPIjs( "GET_PULSE_OUTPUT", device_id, OPEN_VALVE, 0 ); if( ret == 0 ) { my_watch_dog = WATCH_DOG; step_pointer = 30; } break; ///////////////////////////////////////////////////////////////////// // [STEP 30] - TURN ON GRINDING MOTOR ///////////////////////////////////////////////////////////////////// case 30: state_log = "Grinder_Motor_ON"; refreshDisplay(); if( intensity == "INTENSE" ) { aux_delay = 30000; // 35 sec } else if( intensity == "NORMAL" ) { aux_delay = 25000; // 25 sec } else if( intensity == "LIGHT" ) { aux_delay = 10000; // 20 sec } else if( intensity == "TEST" ) { aux_delay = 2000; // 2 sec to test the system } ret = NearAPIjs( "PULSE_OUTPUT", device_id, MOTOR_ON, aux_delay ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 35; } break; ///////////////////////////////////////////////////////////////////// // [STEP 35] - TURN ON GRINDING MOTOR ACK ///////////////////////////////////////////////////////////////////// case 35: state_log = "Waiting: Grinder_Motor_ON_ACK"; refreshDisplay(); ret = NearAPIjs( "GET_PULSE_OUTPUT", device_id, OPEN_VALVE, 0 ); if( ret == 0 ) { my_watch_dog = WATCH_DOG; step_pointer = 40; } break; ///////////////////////////////////////////////////////////////////// // [STEP 40] - CLOSE VALVE ///////////////////////////////////////////////////////////////////// case 40: state_log = "Closing_Valve"; refreshDisplay(); ret = NearAPIjs( "PULSE_OUTPUT", device_id , CLOSE_VALVE, 6000 ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 45; } break; ///////////////////////////////////////////////////////////////////// // [STEP 45] - CLOSE VALVE ACK ///////////////////////////////////////////////////////////////////// case 45: state_log = "Waiting: Close_Valve_ACK"; refreshDisplay(); ret = NearAPIjs( "GET_PULSE_OUTPUT", device_id , CLOSE_VALVE, 6000 ); if( ret == 0 ) { my_watch_dog = WATCH_DOG; step_pointer = 50; } break; ///////////////////////////////////////////////////////////////////// // [STEP 50] - TURN ON HEATER ///////////////////////////////////////////////////////////////////// case 50: state_log = "Turning On Heater..."; refreshDisplay(); ret = NearAPIjs( "DIG_OUTPUT", device_id , HEATER_ON, 1 ); if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; step_pointer = 55; } break; ///////////////////////////////////////////////////////////////////// // [STEP 55] - TURN ON HEATER ACK ///////////////////////////////////////////////////////////////////// case 55: state_log = "Waiting: Heater_ON_ACK"; refreshDisplay(); ret = NearAPIjs( "ADC_INPUT", device_id , THERMOSTAT, 0 ); if( ret == "WAIT" ) { my_watch_dog = WATCH_DOG; step_pointer = 55; } else if( ret < 128 ) { heater = "ON"; my_watch_dog = WATCH_DOG; step_pointer = 60; } else if ( ret > 512 ) { my_watch_dog = WATCH_DOG; step_pointer = 50; } break; ///////////////////////////////////////////////////////////////////// // [STEP 60] - WAIT FOR HEATER OFF ///////////////////////////////////////////////////////////////////// case 60: state_log = "Making Coffee..."; refreshDisplay(); my_watch_dog = WATCH_DOG; ret = NearAPIjs( "ADC_INPUT", device_id , THERMOSTAT, 0 ); if( ret > 512 ) { heater = "OFF"; my_watch_dog = WATCH_DOG; service_run = "NO"; step_pointer = 70; } break; ///////////////////////////////////////////////////////////////////// // [STEP 70] - TURN OFF HEATER ///////////////////////////////////////////////////////////////////// case 70: state_log = "Coffee_Done!!!"; refreshDisplay(); ret = NearAPIjs( "DIG_OUTPUT", device_id , HEATER_ON, 0 ); heater = "OFF"; if( ret == "DONE" ) { my_watch_dog = WATCH_DOG; service_run = "NO"; step_pointer = 5; } break; default: reset_system = 1; step_pointer = 5; break; } }, LOOP_DELAY ); } ); </script> </head> <body> <!-- ****************************************************************************************************************************** --> <!-- * HTML CODE * --> <!-- ****************************************************************************************************************************** --> <p><b> NEARBUS - COFFEE MAKER </b></p> <div id="field_1">Field_1</div> <br /> <div id="field_2">Field_2</div> <br /> <div id="field_3">Field_3</div> <br /> <div id="field_4">Field_4</div> <br /> <div id="field_5">Field_5</div> <br /> <br /> <button onclick="sysStart()">START</button> <br /> <br /> <button onclick="sysStop()">STOP</button> </body> </html>