Skip to content

Instantly share code, notes, and snippets.

@bacall213
Last active December 21, 2015 06:09
Show Gist options
  • Save bacall213/6262094 to your computer and use it in GitHub Desktop.
Save bacall213/6262094 to your computer and use it in GitHub Desktop.
Ninja Temperature/Humidity BETA Dashboard Widget [2W x 1H] [Author: Brian Call] [License: MIT]
return {
"name": "Temperature/Humidity",
"deviceMap": [
{ "deviceId": 31, "vendor": 0, "minimum": 1, "maximum": 1 },
{ "deviceId": 30, "vendor": 0, "minimum": 1, "maximum": 1 }
],
"forceDeviceMapGroup": true
}
/* General column styling */
.column {
width: 50%;
height: 100%;
top: 0%;
position: relative;
float: left;
background: white;
}
/* Left-side label styling (e.g. "Temperature") */
.labelleft {
position: absolute;
top: 80px;
width: 100%;
text-align: center;
color: rgba(0,0,0,0.3);
}
/* Left-side value styling */
.valueleft {
position: absolute;
top: 45px;
width: 100%;
text-align: center;
font-size: 45px;
font-weight: bold;
left: 28px;
.unitsleft {
font-size: 14px;
font-weight: normal;
vertical-align: super;
position: relative;
top: -10px;
}
.hivaltextleft {
position: relative;
display: inline-block;
color: hsl(20,75%,65%);
font-weight: bold;
font-size: 10px;
width: 50px;
top: -15px;
left: -28px;
text-align: left;
}
.lovaltextleft {
position: relative;
display: inline-block;
color: hsl(203,60%,56%);
font-weight: bold;
font-size: 10px;
width: 50px;
top: -33px;
left: 49px;
text-align: left;
}
}
/* Right-side label styling (e.g. "Humidity") */
.labelright {
position: absolute;
top: 80px;
width: 100%;
text-align: center;
color: rgba(0,0,0,0.3);
}
/* Right-side value styling */
.valueright {
position: absolute;
top: 45px;
width: 100%;
text-align: center;
font-size: 45px;
font-weight: bold;
left: 58px;
.unitsright {
font-size: 14px;
font-weight: normal;
vertical-align: super;
position: relative;
top: -10px;
}
.hivaltextright {
position: relative;
display: inline-block;
color: hsl(20,75%,65%);
font-weight: bold;
font-size: 10px;
width: 50px;
top: -15px;
left: -26px;
text-align: left;
}
.lovaltextright {
position: relative;
display: inline-block;
color: hsl(203,60%,56%);
font-weight: bold;
font-size: 10px;
width: 50px;
top: -4px;
left: -89px;
text-align: left;
}
}
/* Sparkline styling */
.sparkline {
position: relative;
top: 105px;
width: 90%;
height: 85px;
margin-left: auto;
margin-right: auto;
line-height: 30px;
border: 1px solid hsl(0,0%,90%);
background: hsl(0,0%,95%);
canvas {
width: 100%;
height: 30px;
}
}
/* Left-side text color */
.sensorleft {
color: hsl(45,100%,45%);
}
/* Right-side text color */
.sensorright {
color: hsl(203,60%,56%);
}
<div class="sensorleft column">
<div class="labelleft">Temperature</div>
<div class="valueleft">
<span class="text"></span>
<sup class="unitsleft">&deg;F</sup>
<span class="hivaltextleft"></span>
<span class="lovaltextleft"></span>
</div>
<div class="sparkline"></div>
</div>
<div class="sensorright column">
<div class="labelright">Humidity</div>
<div class="valueright">
<span class="text"></span>
<sup class="unitsright">%</sup>
<span class="hivaltextright"></span>
<span class="lovaltextright"></span>
</div>
<div class="sparkline"></div>
</div>
/* Define the sparkline sensor graphs */
var sparkSensorRight = element.find(".sensorright .sparkline");
var sparkSensorLeft = element.find(".sensorleft .sparkline");
/* Values from the sensors will be stored in these arrays */
var dataSensorRight = [];
var dataSensorRightTimestamps = [];
var dataSensorLeft = [];
var dataSensorLeftTimestamps = [];
/*
Set celsius/fahrenheit -
F = Fahrenheit
C = Celsius
*/
var temperatureType = "F";
/*
Sparkline (graph) styling options -
chartRangeMinX: Defines the min number of points on the X-axis. This helps set the scale.
chartRanageMaxX: Defines the max number of points on the X-axis
e.g. 1440 updates = 24 hr/day * 60 min/hr
This assumes a data refresh of 1 minute
chartRangeMin: Defines the min value for the Y-axis. Undefined on purpose.
chartRangeMax: Defines the max on the Y-axis. Undefined on purpose.
Humidity should be <= 100%
Fahrenheit: 0 - 150
Celsius: -17 ~ 65
Defining a min/max would require tweaking the range for celsius/fahrenheit.
Let's just not set min/max Y-axis values.
width: Width of the graph data within the "canvas" -
This should be 100% unless you're going with a different style.
height: Height of the graph data within the "canvas" -
This should match the .sparkline "height" variable in the widget CSS.
*/
var sparklineOptionsSensorLeft = {
width: '100%',
height: '85px',
chartRangeMinX: 0,
chartRangeMaxX: 100,
drawNormalOnTop: false,
tooltipPrefix: ' Temperature: ',
tooltipSuffix: '&deg;F',
fillColor: null,
lineColor: 'hsl(45,100%,45%)',
//tooltipFormat: '<span style="color: {{color}}">&#9679;</span> {{prefix}}{{y}}{{suffix}}'
tooltipFormatter: function(sparkline, options, fields) {
return '<div class="jsqfield"><span style="color: ' + fields.color + '">&#9679;</span>' + options.get('tooltipPrefix') + fields.y + options.get('tooltipSuffix') + ' @ ' + dataSensorLeftTimestamps[fields.x] + '</div>';
}
};
var sparklineOptionsSensorRight = {
width: '100%',
height: '85px',
chartRangeMinX: 0,
chartRangeMaxX: 100,
chartRangeMin: 0, // Minimum Y-axis value, 0 < humidity < 100
chartRangeMax: 100, // Maximum Y-axis value, 0 < humidity < 100
drawNormalOnTop: false,
tooltipPrefix: ' Humidity: ',
tooltipSuffix: '%',
fillColor: null,
lineColor: 'hsl(203,60%,56%)',
//tooltipFormat: '<span style="color: {{color}}">&#9679;</span> {{prefix}}{{y}}{{suffix}}'
tooltipFormatter: function(sparkline, options, fields) {
return '<div class="jsqfield"><span style="color: ' + fields.color + '">&#9679;</span>' + options.get('tooltipPrefix') + fields.y + options.get('tooltipSuffix') + ' @ ' + dataSensorRightTimestamps[fields.x] + '</div>';
}
};
// Convert timestamp provided by driver
function sensor_timestamp(timestamp) {
var localTime = new Date(timestamp);
var month = localTime.getMonth() + 1; // Month is 0-11, add 1 to make it 1-12
var day = localTime.getDate();
var year = localTime.getFullYear();
var hours = localTime.getHours();
var minutes = localTime.getMinutes();
var seconds = localTime.getSeconds();
// Months are 1-12, so add "0" in front of 1-9 to conform with ISO 8601
if (month < 10) {
month = "0" + month;
};
// Days are 1-31, so add "0" in front of 1-9 to conform with ISO 8601
if (day < 10) {
day = "0" + day;
};
// Seconds are returned 0-59, so add a "0" at the front if 0-9
if (seconds < 10) {
seconds = "0" + seconds;
};
// Minutes are returns 0-59, so add a "0" at the front if 0-9
if (minutes < 10) {
minutes = "0" + minutes;
};
// Put it together - type 1 = YYYY-MM-DD hh:mm:ss
var timestamp_type1 = year + "-" + month + "-" + day + " " + hours + ":" + minutes + ":" + seconds;
// Put it together - type 2 = hh:mm:ss (YYY-MM-DD)
var timestamp_type2 = hours + ":" + minutes + ":" + seconds + " (" + year + "-" + month + "-" + day + ")";
// Put it together - type 3 = hh:mm:ss YYY-MM-DD
var timestamp_type3 = hours + ":" + minutes + ":" + seconds + " " + year + "-" + month + "-" + day;
// Return timestamp for whatever purpose it's needed for
return timestamp_type2;
};
/* Push values to the right-side sensor display */
function SetSensorRight(value, timestamp) {
/* Update value */
element.find(".sensorright .valueright .text").html(value);
/* Update graph */
dataSensorRight.push(value);
dataSensorRightTimestamps.push(sensor_timestamp(timestamp));
sparkSensorRight.sparkline(dataSensorRight, sparklineOptionsSensorRight);
/* Update high/low values */
element.find(".sensorright .valueright .hivaltextright").html("HI: " + Math.max.apply(null, dataSensorRight));
element.find(".sensorright .valueright .lovaltextright").html("LO: " + Math.min.apply(null, dataSensorRight));
};
/* Push values to the left-side sensor display */
function SetSensorLeft(value, timestamp) {
/* Update value */
element.find(".sensorleft .valueleft .text").html(value);
/* Update data array for graph */
dataSensorLeft.push(value);
dataSensorLeftTimestamps.push(sensor_timestamp(timestamp));
/* Update graph */
sparkSensorLeft.sparkline(dataSensorLeft, sparklineOptionsSensorLeft);
/* Update high/low values */
element.find(".sensorleft .valueleft .hivaltextleft").html("HI: " + Math.max.apply(null, dataSensorLeft));
element.find(".sensorleft .valueleft .lovaltextleft").html("LO: " + Math.min.apply(null, dataSensorLeft));
};
/* Activate our update functions only when new data is received */
scope.onData = function(data) {
/* Device ID 30 = 433 MHz humidity sensor */
if (data.D === 30) {
SetSensorRight(data.DA, data.timestamp);
};
/* Device ID 31 = 433 MHz temperature sensor */
if (data.D === 31) {
if (temperatureType === "F") {
/* Convert to fahrenheit */
F = (data.DA * 9 / 5 + 32).toFixed(2);
SetSensorLeft(F, data.timestamp);
}
else if (temperatureType === "C") {
/* Celsius */
SetSensorLeft(data.DA, data.timestamp)
}
else {
/* Assume fahrenheit - but this should never be reached */
/* Convert to fahrenheit */
F = (data.DA * 9 / 5 + 32).toFixed(2);
SetSensorLeft(F, data.timestamp);
};
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment