Posted on

ESP8266 NodeMCU – Toggle Button & Slider – Remote Node.js Server Example

After looking all over for bits and pieces of how to properly get a Remote Node.js Server to communicate with a ESP8266 NodeMCU, I was finally able to get everything working properly. With so many libraries of the same variant of implementing a Socket.io client on a NodeMCU, it was very confusing when functions had the same or very similar names and arguments.

I wanted a way to remotely control a device with a button toggle switch (LED, Relay etc) and a range slider to control brightness of an LED, Triac etc with a web based interface on a NodeMCU.

Here is an example of how I was able to achieve it with fairly great results. Hopefully this helps others in trying to achieve the same results. For more buttons and sliders their values can be stored in 2 arrays one for switch state values and another for dimmer pwm values.

Below is the Server.js file running on the remote Node.js Web Server :


var http = require('http');

var express = require('express');

var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);

app.get('/', function (req, res) {

res.sendFile(__dirname + '/index.html');

});
app.use(express.static(__dirname + '/'));

var server = http.createServer(app);

var io = require('socket.io').listen(server);

server.listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});

// Define/initialize our global vars
var socketCount = 0

var brightness = 0; //static variable to hold the current brightness
var swstate = 0;

io.sockets.on('connection', function(socket){
//console.log(socket.id);
// Socket has connected, increase socket count
socketCount++
// Let all sockets know how many are connected
io.sockets.emit('users connected', socketCount)

socket.emit('swstate', swstate);

socket.on('swstate',function(){
swstate = 1 - swstate;
//console.log(swstate);
io.emit('swstate', swstate);
});

socket.emit('led', {value: brightness}); //send the new client the current brightness

socket.on('led', function (data) { //makes the socket react to 'led' packets by calling this function
brightness = data.value; //updates brightness from the data object
io.sockets.emit('led', {value: brightness}); //sends the updated brightness to all connected clients
});

});

process.on('SIGINT', function() {
//Do things on Script Termination...
console.log('\n Bye!')
process.exit();
});

Start the node.js server script on the remote server using the command in SSH:
forever start -o out.log -e err.log Server.js

Below is the index.html file running in the same directory as the Node.js Script (This page is served by the Node.js http Server) :

<html>
<head>
<title>Node.js Socket.io Testing</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link href="https://gitcdn.github.io/bootstrap-toggle/2.2.2/css/bootstrap-toggle.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-switch/3.3.2/css/bootstrap2/bootstrap-switch.min.css">
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22http%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fjquery%2F1.11.3%2Fjquery.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Frangeslider.js%2F2.3.2%2Frangeslider.min.css%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<!--[if IE]>
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fjson3%2F3.3.2%2Fjson3.min.js%22%3E%0A%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fsocket.io%2F2.1.1%2Fsocket.io.dev.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<![endif]-->
<!--[if !IE]><!-->
<!--<![endif]-->
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22%2Fsocket.io%2Fsocket.io.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fmaxcdn.bootstrapcdn.com%2Fbootstrap%2F3.3.5%2Fjs%2Fbootstrap.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Fbootstrap-switch%2F3.3.2%2Fjs%2Fbootstrap-switch.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fgitcdn.github.io%2Fbootstrap-toggle%2F2.2.2%2Fjs%2Fbootstrap-toggle.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20src%3D%22https%3A%2F%2Fcdnjs.cloudflare.com%2Fajax%2Flibs%2Frangeslider.js%2F2.3.2%2Frangeslider.min.js%22%3E%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cstyle%3E%0Abody%20%7B%0Amargin-top%3A%2020px%3B%0Amargin-left%3A%2030px%3B%0A%7D%0A%0Ainput%5Btype%3Drange%5D%7B%0A-webkit-appearance%3A%20none%3B%0Awidth%3A%2080%25%3B%0A%7D%0A%0Ainput%5Btype%3Drange%5D%3A%3A-webkit-slider-runnable-track%20%7B%0Aheight%3A%2010px%3B%0Abackground%3A%20%230c75b3%3B%0Aborder%3A%20none%3B%0Aborder-radius%3A%203px%3B%0A%7D%0A%0Ainput%5Btype%3Drange%5D%3A%3A-webkit-slider-thumb%20%7B%0A-webkit-appearance%3A%20none%3B%0Aborder%3A%20none%3B%0Aheight%3A%2032px%3B%0Awidth%3A%2032px%3B%0Aborder-radius%3A%2050%25%3B%0Abackground%3A%20%2314c0dc%3B%0Amargin-top%3A%20-12px%3B%0A%7D%0A%0Ainput%5Btype%3Drange%5D%3Afocus%20%7B%0Aoutline%3A%20none%3B%0A%7D%0A%0Ainput%5Btype%3Drange%5D%3Afocus%3A%3A-webkit-slider-runnable-track%20%7B%0Abackground%3A%20%230c75b3%3B%0A%7D%0A%3C%2Fstyle%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<style>" title="<style>" />

</head>
<body>


<div class="row">


<div class="alert alert-info col-md-3 col-md-3" role="alert" id="usersConnected"></div>

</div>





<strong>Slider Value: </strong><span id="outputText">50</span>

<input type="range" id= "inputSlider" min="0" max="1023" value="0" step="1" oninput="showValue(this.value)" />


<strong>SW State: </strong><span id="swval"></span>

<input type="checkbox" data-toggle="toggle" data-on="Off" data-off="On" id="toggle">

<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-wp-preserve="%3Cscript%20type%3D%22text%2Fjavascript%22%3E%0A%0A%2F%2F%20Connect%20to%20our%20node%2Fwebsockets%20server%0Avar%20socket%20%3D%20io.connect('http%3A%2F%2Fwww.domain.com%3A3000')%3B%0A%0Avar%20websocket%20%3D%200%3B%0A%0A%24(%22%23toggle%22).change(function()%7B%0Aif(!websocket)%20%7B%0Aif(%24(%22%23toggle%22).prop(%22checked%22)%20%3D%3D%201)%7B%0Avar%20swstate%20%3D%201%3B%0Asocket.emit('swstate'%2C%20swstate)%3B%0A%7Delse%7B%0Avar%20swstate%20%3D%200%3B%0Asocket.emit('swstate'%2C%20swstate)%3B%0A%7D%0A%7D%20else%20%7Bwebsocket%20%3D%200%3B%7D%0A%7D)%3B%0A%0Asocket.on('swstate'%2C%20function(swstate)%20%7B%0AswValue(swstate)%3B%0Awebsocket%20%3D%201%3B%0Aif(swstate%20%3D%3D%3D%201)%7B%0A%24('%23toggle').bootstrapToggle('on')%3B%7D%0Aelse%7B%0A%24('%23toggle').bootstrapToggle('off')%3B%7D%0A%0A%7D)%3B%0A%2F%2F%20New%20socket%20connected%2C%20display%20new%20count%20on%20page%0Asocket.on('users%20connected'%2C%20function(data)%7B%0A%24('%23usersConnected').html('%3Cstrong%3EUsers%20Connected%3A%3C%2Fstrong%3E%20'%20%2B%20data)%0A%7D)%0A%0Asocket.on('led'%2C%20function%20(data)%20%7B%0Adocument.getElementById(%22inputSlider%22).value%20%3D%20data.value%3B%0Adocument.getElementById(%22outputText%22).innerHTML%20%3D%20data.value%3B%0A%7D)%3B%0A%0Afunction%20showValue(newValue)%0A%7B%0Adocument.getElementById(%22outputText%22).innerHTML%3DnewValue%3B%0Asocket.emit('led'%2C%20%7B%20value%3A%20newValue%20%7D)%3B%0A%7D%0Afunction%20swValue(swstate)%0A%7B%0Adocument.getElementById(%22swval%22).innerHTML%3Dswstate%3B%0A%7D%0A%2F%2F%7D)%0A%3C%2Fscript%3E" data-mce-resize="false" data-mce-placeholder="1" class="mce-object" width="20" height="20" alt="<script>" title="<script>" />
</body>
</html>

Below is the Code for the ESP8266 NodeMCU programmed on the Arduino IDE (v1.8.5) environment:

#include <ESP8266WiFi.h>          //ESP8266 Core WiFi Library (you most likely already have this in your sketch)</pre>

//#include <DNSServer.h> //Local DNS Server used for redirecting all requests to the configuration portal
#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
#include <WiFiManager.h> //https://github.com/tzapu/WiFiManager WiFi Configuration Magic
#include <ESP8266mDNS.h>
#include <SocketIoClient.h>
#include <ArduinoJson.h>

#define LED 13
// Pin D7 on NodeMCU
#define LEDPWM 12
// Pin D6 on NodeMCU

const char* mdnsName = "esp8266";

// DNS server
const byte DNS_PORT = 53;
DNSServer dnsServer;

ESP8266WebServer webServer(80);

SocketIoClient socket;

void light(const char * payload, size_t length) {
String msg;
//String text = String((char *) &payload[0]);
msg = String((char*)payload);
if(msg=="1"){ digitalWrite(LED,HIGH); Serial.println("LED ON");}else{digitalWrite(LED,LOW); Serial.println("LED OFF");}
Serial.println(msg);
}

void lightpwm(const char * payload, size_t length) {

DynamicJsonBuffer jsonBuffer(JSON_OBJECT_SIZE(4) + 100);

//String text = String((char *) &payload[0]);
//String msg2 = String((char*)payload);

JsonObject& root = jsonBuffer.parseObject(String((char*)payload));
int pwmval = root["value"];
//Serial.println("PWM LED");
analogWrite(LEDPWM, pwmval);
}

String responseHTML = ""
"<!DOCTYPE html><html><head><title>Hello World!</title></head><body>"
"
<h1>Hello World!</h1>

All requests are redirected here.

</body></html>";

//flag for saving data
bool shouldSaveConfig = false;

void configModeCallback (WiFiManager *myWiFiManager) {
Serial.println("Entered config mode");
Serial.println(WiFi.softAPIP());
Serial.println(myWiFiManager->getConfigPortalSSID());
}

//callback notifying us of the need to save config
void saveConfigCallback () {
Serial.println("Should save config");
shouldSaveConfig = true;
}

void setup() {
// put your setup code here, to run once:
pinMode(LED, OUTPUT);
pinMode(LEDPWM, OUTPUT);
digitalWrite(LED, LOW);
Serial.begin(115200);
WiFiManager wifiManager;
//reset settings - for testing
//wifiManager.resetSettings();
wifiManager.setConfigPortalTimeout(360);
wifiManager.setDebugOutput(false);

wifiManager.setAPCallback(configModeCallback);
//WiFiManager.setHostname(mdnsName);
//fetches ssid and pass and tries to connect
//if it does not connect it starts an access point with the specified name
//here "AutoConnectAP"
//and goes into a blocking loop awaiting configuration
if(!wifiManager.autoConnect("Allen_LED", "1234pass")) {
Serial.println("failed to connect and hit timeout");
//reset and try again, or maybe put it to deep sleep
ESP.reset();
delay(1000);
}
wifiManager.setSaveConfigCallback(saveConfigCallback);

//if you get here you have connected to the WiFi
Serial.println("Connected!... YES!");
Serial.println("Local IP is: ");
Serial.println(WiFi.localIP());
WiFi.hostname(mdnsName);
if (!MDNS.begin(mdnsName, WiFi.localIP())) {
// Start the mDNS responder for esp8266.local
Serial.println("Error setting up MDNS responder!");
}
Serial.println("mDNS responder started");
// Add service to MDNS-SD
MDNS.addService("http", "tcp", 80);
MDNS.addServiceTxt("http", "tcp", "url", "http://esp8266.local");

socket.begin("www.domain.com", 3000, "/socket.io/?transport=websocket");
//socket.on("event", event);
socket.on("swstate", light);
socket.on("led", lightpwm);

// HTTP Basic Authorization (optional)
//webSocket.setAuthorization("username", "password");

//socket.emit("plainString", "\"this is a plain string\"");
//socket.emit("swstate", "1");

// replay to all requests with same HTML
webServer.onNotFound([]() {
webServer.send(200, "text/html", responseHTML);
});
webServer.begin();
}

void loop() {
// put your main code here, to run repeatedly:
dnsServer.processNextRequest();
webServer.handleClient();
socket.loop();
}

The end result will look like the screenshot below where the Button Switch controls Pin D7 on the NodeMCU, and the Slider will create a PWM Dimmer on Pin D6, which you can connect an LED to see the brightness level correspond to the slider in just about real-time.

One side note: Make sure you replace domain.com in all the code above to reflect where your node.js server is running, localhost, ip, domain, hostname etc.

Posted on

Banquet & Hospitality Facility Lighting

How LED Lighting / Entertainment & Specialty Lighting Affects Banquet Halls?

Banquet Facility & Hospitality Clients today are noticing things like lighting, its an important aspect that was previously overlooked in the banquet & hospitality industry.

For example in a banquet facility, there is only so much a DJ or lighting company can do via mobile or rental service besides up-lighting walls and moving lights around the stage, or around the dance floor area.

That’s why it’s important a banquet or hospitality facility considers things such as lighting in new building construction or when revamping existing systems.

If your always asking yourself how to fix banquet hall lighting, a lighting company specializing in entertainment lighting is probably your best bet.
At Allen Productions, we understand the newest trends in lighting as electrical engineers from both the customers point of view and also technical standpoint.

We think of the future in our projects, for easier expansion and updates. Check out some of our customers and projects on our project portfolio, we cater to some of the top banquet facilities in Southern California, the entertainment capital of the world.

We look forward to further discussing our services with you to determine how we can beautify your venue(s). Contact us today!

Posted on

Wayne Nucleus to Gilbarco Passport POS UPC & Pricebook Conversion

Having worked on a custom application for a petroleum c-store & back office company, we have created a Dresser Wayne Nucleus to Gilbarco Passport POS parsing system for converting the UPC’s, Departments & Pricebook, following the NAXML 3.3 POS standard structure.

We have an ultra fast parser developed to convert:
Nucleus: .DAT files (must contain UPCs) to Passport: ITT, MCT, TaxMaintenance XML files.

How the process works:
Your technician provides us with the previous nucleus .DAT file containing the UPC / PLUs and your current Passport ITT, MCT, TaxMaintenance XML files, we provide the conversion process and generate new ITT, MCT, TaxMaintenance XML files to your technician and you (in case you need them for your back office system).

Contact us for conversion pricing (less than $500 per location), one time cost covered until conversion is the way you want, free file analysis, we will beat anyone’s advertised price for price-book conversion!

Posted on

New: Lighting Installation – Metropol Classic Banquet Hall – State of the Art Lighting System

New Lighting Installation – Featuring State of the Art LED Lighting System
Location: Metropol Classic Banquet Hall – Glendale, California
Installation Time Frame: 60 Days

Video of Completed Install Project During a Private Event:

Video During Lighting Programming of Installation:

Test of Slow Movements:

Preparing the Wiring of Installation & Termination:

Posted on

MSD250, MSD575, MSD1200 to LED Retrofit Kits Made For Moving Head Spot Lighting Fixtures 150w to 1200w HID MSD HMI Type

Allen Productions has been working on a New LED Retrofit Kit Designed to Replace MSD / HMI Lamps in Moving Head Spot or Wash Lighting Fixtures 150-Watt to 1200-Watt. If you are a touring company, a rental house, or have a permanently installed rig of moving heads, this retrofit is for you! IT WILL VOID YOUR WARRANTY because it requires a bit of modification of your light fixture to fit the LED module into place, and replacing your existing heavy ballast and igniters in the fixture with an LED ballast.

Posted on

Batman – The Dark Knight Rises – Magnus Rex – July 20 – Bomb Truck Scene Crane

Allen A. Working as Bobs Towing’s Technical Director, we got the opportunity to transport and move around a large “bomb carrying” truck for the Batman “The Dark Knight Rises”, code-name (“Magnus Rex”) Movie Set, which is set to air on July 20th in Theaters near you. Below are some images of the owner of Allen Productions & their crew, and the Bob’s Towing Equipment (Rotator / Crane & Special Equipment) Used. Remember if you just need a Tow or have a need to move large heavy equipment for a movie set, they can handle Any Job! Call 1(800) BobsTow. Allen Productions also has a department for Special Effects, worldwide experts in “Control Electronics” to Special Effects Lighting & High Powered Lasers, to Pyrotechnics for the motion picture, television and entertainment industries including Video Synchronized Effects based on SMTPE & various other industry standard methods of synchronization. Are you a Movie Producer? Have a Technical Need? Problem? Need Help? or Just Want Solutions? We Can Help You! Call Us Today at (562) 242-8479! Be Sure To Ask for Allen!

Special Thanks To Warner Brothers & the other Production Companies Involved! If your company was also a part of this film / scene and would like to be featured on this page please contact us.

 Allen Productions Exclusive Photos Below:
All Rights Reserved! DO NOT COPY ANY PHOTOS WITHOUT WRITTEN PERMISSION!

Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck
Batman - Dark Knight Rises - Bomb Truck
Batman – Dark Knight Rises – Bomb Truck