Skip to content

Instantly share code, notes, and snippets.

@timcunningham
Created November 29, 2012 16:38
Show Gist options
  • Save timcunningham/4170227 to your computer and use it in GitHub Desktop.
Save timcunningham/4170227 to your computer and use it in GitHub Desktop.
ColdFusion 10 Web sockets getting started
<cfset this.name="ampMeter">
<!-- This setups a web socket named meter1 -->
<cfset this.wschannels = [{name="meter1"}]>
When ColdFusion 10 was in early beta, I was really interested in playing with web sockets. Unfortunately I was only *playing* with them, I didn't have a real world need. So when Ray Camden wrote several demos that showed how web sockets would work, I ran the code, saw that it worked and then moved on to test something else. Long story short, I understood the principles of web sockets, without really know how to write one: till now.
At work we have two server rooms, they are on full UPS battery backup and natural gas generator. The generators each have a 70 amp breaker, so if the amperage load is around 70 amps and we lose power, the generator is going to trip and our server room will lose power. Do not ask me how I know this. I don't want to talk about it.
Anyway we purchased a neat little device called <a href="http://www.theenergydetective.com/">The Energy Detective (TED)</a> which measures the power flow being pulled from each server room. TED has a a really nice dash board that tells me many interesting stats, everything but, (you guessed it) amperage. True, I could do a simple division on the kVA, but math is hard. So web sockets to the rescue! First I re-read Evelin Varghese from Adobe's blog article about <a href="http://www.eveysijo.com/2012/02/coldfusion-websocket-for-absolute.html">ColdFusion WebSocket Part1:Getting Started</a>
For this implementation of web sockets we will need the following:
1. Set up a web socket channel name in application.cfc
2. Push information to the channel
3. Set up a page that listens to the channel
4. Write javascript that displays the information that comes from the channel.
The code below in application.cfc sets up a web socket named meter1
application.cfc
PublishMessage.cfm pushes the current amperage to the web socket we set up in application.cfc
publishMessage.cfm
Subscriber.cfm listens to the channel meter1 and puts it into javascript object we named messageHandler. Anything pushed down the tube in publishmessage.cfm is going to show up on subscriber.cfm (without any page refreshing mumbo jumbo)
Subscriber.cfm
Once I saw the data update all by itself, the web sockets made perfect sense. It is really one of those things you have to watch in action to "get" You can see it here: <a href="http://services.cfmumbojumbo.com/ampmeter/subscriber.cfm">http://services.cfmumbojumbo.com/ampmeter/subscriber.cfm</a>
Finally, I wanted to make the data pretty, so I found RGraph which has a thermometer chart that uses HTML5 Canvas:
index.cfm
Mocked up demo: <a href="http://services.cfmumbojumbo.com/ampmeter/">http://services.cfmumbojumbo.com/ampmeter/</a>
<!-- cfwebsocket subscribes to the websocket named meter1. Meter1 was created in application.cfc and messages
are being pushed to it on the publishmessage.cfm page. Anything pushed to the socket will be available
via a javascript object referenced in this case as messageHandler -->
<cfwebsocket name="myWS" onmessage="messageHandler" subscribeto="meter1" >
<!DOCTYPE html >
<html>
<head>
<link rel="stylesheet" href="./RGraph/demos/demos.css" type="text/css" media="screen" />
<script src="./RGraph/libraries/RGraph.common.core.js" ></script>
<script src="./RGraph/libraries/RGraph.common.dynamic.js" ></script>
<script src="./RGraph/libraries/RGraph.common.tooltips.js" ></script>
<script src="./RGraph/libraries/RGraph.thermometer.js" ></script>
<!--[if lt IE 9]><script src="./RGraph/excanvas/excanvas.js"></script><![endif]-->
<title>Amps</title>
</head>
<body>
<center>
<h1>Amp load</h1>
<script type="text/JavaScript">
function messageHandler(messageobj)
{
//Converting the JS object to a string and display in "myDiv"
var message = ColdFusion.JSON.encode(messageobj);
var txt=document.getElementById("myDiv");
//txt.innerHTML +=message + "<br>" ;
var amps = messageobj.data;
var color = getTempColor(amps);
var HostingServerRoom = new RGraph.Thermometer('cvs', 0,75,amps);
HostingServerRoom.Set('chart.colors', [color]);
HostingServerRoom.Set('chart.scale.decimals', 2);
HostingServerRoom.Draw();
}
//function to control the color of the graph
function getTempColor(amp)
{
var color = "red";
if (amp >= 70)
{color="red";
return color;}
else if (amp >=50)
{color="orange";
return color;}
else if (amp >=30)
{color="green";
return color;}
else if (amp >=0)
{color="blue";
return color;}
return color;
}
</script>
<div id="myDiv"><!-- for debug output --></div>
<canvas id="cvs" width="100" height="400">[No canvas support]</canvas>
</center>
</body>
<cfcomponent hint="fake component set up to simulate calls to amp meter">
<cffunction name="getLiveData">
<cfreturn randrange(5,70)>
</cffunction>
</cfcomponent>
<!-- Call my "fake api" which returns a random number of amps. I set up a scheduled job
that calls this page every 5 seconds -->
<cfset amps = createobject("component","LiveDataApi").getLiveData()>
<!-- Push the number to the web socket named Meter1 -->
<cfset wspublish("Meter1", amps)>
<!--- Below is unneeded output so you can see the data --->
<cfoutput>#amps#</cfoutput>
<cfwebsocket name="myWS" onmessage="messageHandler" subscribeto="meter1" >
<!DOCTYPE html >
<html>
<head>
<title>Amps</title>
</head>
<body>
<center>
<h1>Amp load</h1>
<script type="text/JavaScript">
function messageHandler(messageobj)
{
//Converting the JS object to a string and display in "myDiv"
var message = ColdFusion.JSON.encode(messageobj);
var txt=document.getElementById("myDiv");
txt.innerHTML +=message + "<br>" ;
var amps = messageobj.data;
}
</script>
<div id="myDiv"></div>
</center>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment