www.homeseer.com    
 

Go Back   HomeSeer Message Board > HomeSeer Products & Services > HomeSeer General Discussion Area

HomeSeer General Discussion Area General discussion about HomeSeer that does not fall into any other category or are not specific to 1.x or 2.x versions of HomeSeer.

Reply
 
Thread Tools Display Modes
  #1  
Old February 13th, 2017, 10:58 PM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
Please help me get QLC (Qlight) working.

So I have been working on this problem for the last 8 hours. I have searched every forum on here and everywhere else. Unfortunately, I don't understand how API POST and GET works all too well.
.
I am trying to do something quite simple which is just trigger a single button for QLC. These control the garden lights and this program seems to work the best. I cannot for the life of me figure out how to get homeseer to trigger it.
.
The webserver for QLC is 192.168.0.2:9999 for me. On inspecting the element of the button on the webpage of QLC its says ID31 not that I'm even sure it means anything.
.
I'd had assumed this website http://www.qlcplus.org/Test_Web_API.html would have helped me but it didn't. The function ID is 48 on this web page. The function type is Scene and currently, function status is "stopped".
.
I need some script to trigger the button on but can't find code similar to make it work.
.
Also, I have tried used Keyboard pressed to toggle function but this program does not see the presses or react to them. Neither does AutoIT.
.
Appreciate any help given. I am struggling with this one.
Reply With Quote
  #2  
Old February 14th, 2017, 11:49 AM
mrhappy mrhappy is offline
OverSeer
 
Join Date: Nov 2007
Location: W.Mids, UK
Posts: 7,085
HTTP POST/GET should be relatively easy to get working with some of the existing scripting calls (hs.geturl/hs.urlaction) however it is not clear on that page what the commands actually are - do you have a document listing them?
Reply With Quote
  #3  
Old February 14th, 2017, 09:29 PM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
Unfortunately, in all the forums I have found I could not find any. I will do some more research into finding them. I have also submitted a post on the QLC forum to see if someone there can help me with the commands.
.
Thanks
Reply With Quote
  #4  
Old February 14th, 2017, 09:39 PM
sparkman's Avatar
sparkman sparkman is offline
OverSeer
 
Join Date: Oct 2001
Location: Calgary, Alberta, Canada
Posts: 6,007
Quote:
Originally Posted by shirec View Post
Unfortunately, in all the forums I have found I could not find any. I will do some more research into finding them. I have also submitted a post on the QLC forum to see if someone there can help me with the commands.
.
Thanks
Do a "view source" on the html page of the local server and post it here. Maybe someone can spot something in it that can be used.

Cheers
Al
__________________
HS3Pro 3.0.0.318 on Jetway JBC501F9Q-Q87-B i7 8GB 1874 Devices, 955 Events, 28 Plugins
Z-Wave 3.0.1.131 Z-Net 105 nodes:Leviton Vizia,Kwikset,FortrezZ Valve/Sensors,Everspring Sensors/Modules/Outlets,CT30 Stats,MIMOLites,Aeotec Smart Switches
RFXCom W800,RFXrec433,RFXtrx433|APCUPSD|Pushover|Squeezebox|weatherXML|HS Phone W2C|APCUPSD|UltraLog
UltraGCIR GC-100|UltraNetcam|UltraPioneer|Ultra1Wire|DSC PC1832|BLLED|BLTVGuide|ImperiHome|jon00 Utilities|MySensors

PHLocation|X10 CM11A IOLinc,etc
Reply With Quote
  #5  
Old February 14th, 2017, 10:18 PM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
Well its not exactly simple but I believe this is the code for the web API and contains the commands in some form.

I believe this is one of them to get the status. The status I would be getting is for widget 31. It's also 0 = off and 255 = on

Code:
 <div class="apiButton" onclick="javascript:requestAPIWithParam('getWidgetStatus', 'wStatusID');">getWidgetStatus</div>
    Widget ID:<input id="wStatusID" type="text" value="0">
  </td>
  <td>Retrieve the status of a Virtual Console Widget with the given ID</td>
  <td><div id="getWidgetStatusBox" class="resultBox"></div></td>
 </tr>
This is the code to change the status to 255 or 0.

Code:
<div class="apiButton" onclick="javascript:vcWidgetSetValue('basicWidgetID', 'basicWidgetValue');">Basic widget value set</div>

   Widget ID:<input id="basicWidgetID" type="text" value="0">
   Value:<input id="basicWidgetValue" type="text" value="255">
  </td>
  <td colspan="2">
    This API is the direct way to set a Virtual Console widget value. It can be used for Buttons, Sliders and
    Audio Triggers. The value to set depends on the widget type itself. Buttons and Audio triggers will only support values 0 (= off) and 255 (= on) while Sliders will accept all the values in the 0-255 range.
  </td>
This is the full code as listed on that web page.

Code:
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>QLC+ Web API Test</title>
<script type="text/javascript">
// the WebSocket instance
var websocket;
var isConnected = false;
// the websocket host location
var wshost = "http://127.0.0.1:9999";
// helper function to send QLC+ API commands
function requestAPI(cmd) 
{
  if (isConnected == true)
    websocket.send("QLC+API|" + cmd);
  else
    alert("You must connect to QLC+ WebSocket first !");
}
// helper function to send a QLC+ API with one parameter.
// The specified parameter is not a value, but a CSS object
// from which a value is retrieved (usually a <input> box)
function requestAPIWithParam(cmd, paramObjName) 
{
  var obj = document.getElementById(paramObjName);
  if (obj)
  {
    if (isConnected == true)
      websocket.send("QLC+API|" + cmd + "|" + obj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function requestChannelsRange(cmd, uniObjName, addressObjName, rangeObjName) 
{
  var uniObj = document.getElementById(uniObjName);
  var addrObj = document.getElementById(addressObjName);
  var rangeObj = document.getElementById(rangeObjName);
  if (uniObj && addrObj && rangeObj)
  {
    if (isConnected == true)
      websocket.send("QLC+API|" + cmd + "|" + uniObj.value + "|" + addrObj.value + "|" + rangeObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function setSimpleDeskChannel(addressObjName, channelValueObjName)
{
  var addrObj = document.getElementById(addressObjName);
  var valObj = document.getElementById(channelValueObjName);
  if (addrObj && valObj)
  {
    if (isConnected == true)
      websocket.send("CH|" + addrObj.value + "|" + valObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function vcWidgetSetValue(wIDObjName, wValueObjName)
{
  var wObj = document.getElementById(wIDObjName);
  var valObj = document.getElementById(wValueObjName);
  if (wObj && valObj)
  {
    if (isConnected == true)
      websocket.send(wObj.value + "|" + valObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function vcCueListControl(clIDObjName, clOpObjName, clStepObjName)
{
  var clObj = document.getElementById(clIDObjName);
  var opObj = document.getElementById(clOpObjName);
  var stepObj = document.getElementById(clStepObjName);
  if (clObj && opObj)
  {
    if (isConnected == true)
    {
      if (opObj.value == "STEP")
        websocket.send(clObj.value + "|" + opObj.value + "|" + stepObj.value);
      else
        websocket.send(clObj.value + "|" + opObj.value);
    }
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function vcFrameControl(frIDObjName, frOperation)
{
  var frObj = document.getElementById(frIDObjName);
  var opObj = document.getElementById(frOperation);
  if (frObj && opObj)
  {
    if (isConnected == true)
    {
        websocket.send(frObj.value + "|" + opObj.value);
    }
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}
function connectToWebSocket(host) {
  var url = 'ws://' + host + '/qlcplusWS';
  websocket = new WebSocket(url);
  // update the host information
  wshost = "http://" + host;
  websocket.onopen = function(ev) {
    //alert("QLC+ connection successful");
    document.getElementById('connStatus').innerHTML = "<font color=green>Connected</font>";
    isConnected = true;
  };
  websocket.onclose = function(ev) {
    alert("QLC+ connection lost !");
  };
  websocket.onerror = function(ev) {
    alert("QLC+ connection error!");
  };
 
  // WebSocket message handler. This is where async events
  // will be shown or processed as needed
  websocket.onmessage = function(ev) {
    // Uncomment the following line to display the received message
    //alert(ev.data);
    // Event data is formatted as follows: "QLC+API|API name|arguments"
    // Arguments vary depending on the API called
    var msgParams = ev.data.split('|');
    
    if (msgParams[0] == "QLC+API")
    {
      if (msgParams[1] == "getFunctionsNumber")
	document.getElementById('getFunctionsNumberBox').innerHTML = msgParams[2];
      
      // Arguments is an array formatted as follows: 
      // Function ID|Function name|Function ID|Function name|...
      else if (msgParams[1] == "getFunctionsList")
      {
	var tableCode = "<table class='apiTable'><tr><th>ID</th><th>Name</th></tr>";
	for (i = 2; i < msgParams.length; i+=2)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('getFunctionsListBox').innerHTML = tableCode;
      }
      else if (msgParams[1] == "getFunctionType")
	document.getElementById('getFunctionTypeBox').innerHTML = msgParams[2];
      else if (msgParams[1] == "getFunctionStatus")
	document.getElementById('getFunctionStatusBox').innerHTML = msgParams[2];
      else if (msgParams[1] == "getWidgetsNumber")
	document.getElementById('getWidgetsNumberBox').innerHTML = msgParams[2];
      
      // Arguments is an array formatted as follows: 
      // Widget ID|Widget name|Widget ID|Widget name|...
      else if (msgParams[1] == "getWidgetsList")
      {
	var tableCode = "<table class='apiTable'><tr><th>ID</th><th>Name</th></tr>";
	for (i = 2; i < msgParams.length; i+=2)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('getWidgetsListBox').innerHTML = tableCode;
      }
      
      else if (msgParams[1] == "getWidgetType")
	document.getElementById('getWidgetTypeBox').innerHTML = msgParams[2];
	
      else if (msgParams[1] == "getWidgetStatus")
      {
	var status = msgParams[2];
	if (msgParams[2] == "PLAY")
	  status = msgParams[2] + "(Step: " + msgParams[3] + ")";
	document.getElementById('getWidgetStatusBox').innerHTML = status;
      }
      
      else if (msgParams[1] == "getChannelsValues")
      {
	var tableCode = "<table class='apiTable'><tr><th>Index</th><th>Value</th><th>Type</th></tr>";
	for (i = 2; i < msgParams.length; i+=3)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td><td>" + msgParams[i + 2] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('requestChannelsRangeBox').innerHTML = tableCode;
      }
    }
  };
};
function loadProject () {
  var formAction = wshost + "/loadProject";
  document.getElementById('lpForm').action = formAction;
}
</script>

<style type="text/css">
body { 
  background-color: #45484d;
  color: white;
  font:normal 18px/1.2em sans-serif;
}
iframe {
  position: absolute;
  display: block;
  height: 100%;
  width: 100%;
  -moz-border-radius: 12px;
  -webkit-border-radius: 12px; 
  border-radius: 12px; 
  -moz-box-shadow: 4px 4px 14px #000; 
  -webkit-box-shadow: 4px 4px 14px #000; 
  box-shadow: 4px 4px 14px #000; 
}
#prjBox {
  position: absolute;
  width: 50%;
  height: 70%;
  margin-top: 0px;
  margin-left: 47%;
}
.apiTable {
  border-collapse: collapse;
}
.apiTable th {
  font-size: 18px;
  color: white;
  border: solid 1px white;
}
.apiTable tr {
  font-size: 14px; 
  border: solid 1px white;
}
.apiTable td {
  border: solid 1px white;
  padding: 2px 5px 2px 5px;
  margin: 0 5px 0 5px;
}
.apiButton {
  display: table-cell; 
  vertical-align: middle;
  text-align: center;
  color: black;
  cursor:pointer;
  height: 30px;
  padding: 0 10px 0 10px;
  background: #4477a1;
  background: -webkit-gradient(linear, left top, left bottom, from(#81a8cb), to(#4477a1) );
  background: -moz-linear-gradient(-90deg, #81a8cb, #4477a1);
  -moz-border-radius: 6px;
  -webkit-border-radius: 6px; 
  border-radius: 6px; 
}
.apiButton:hover {
  background: #81a8cb;
  background: -webkit-gradient(linear, left top, left bottom, from(#4477a1), to(#81a8cb) );
  background: -moz-linear-gradient(-90deg, #4477a1, #81a8cb);
}
.resultBox {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  color: #000;
  width: 150px;
  height: 30px;
  background-color: #aaaaaa;
  border-radius: 6px; 
}
</style>

<body>

<h2>Q Light Controller+ Web API test page</h2>

<!-- ############## Project box to display what QLC+ is doing ####################### -->
<div id="prjBox"><iframe name="projectFrame" src="" id="projectFrame"></iframe></div>

<!-- ############## Websocket connection code ####################### -->
QLC+ IP: 
<input type="text" id="qlcplusIP" value="127.0.0.1:9999"/>
<input type="button" value="Connect" onclick="javascript:connectToWebSocket(document.getElementById('qlcplusIP').value);">
<div id="connStatus" style="display: inline-block;"><font color=red>Not connected</font></div>
<br><br>

<!-- ############## Project load code ####################### -->
<form id="lpForm" onsubmit="loadProject()" method="POST" enctype="multipart/form-data" target="projectFrame">
Load a project:
<input id="loadTrigger" type="file" onchange="document.getElementById('submitTrigger').click();" name="qlcprj">
<input id="submitTrigger" type="submit">
</form>
<br><br>

<!-- ############## Individual API tests ####################### -->

<table class="apiTable" width=45%>
 <tr>
  <th width=30%><b>API Function</b></th>
  <th width=30%><b>Description</b></th>
  <th width=40%><b>Result</b></th>
 </tr>
 
<!-- ############## Channels API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>Channels APIs</b></td>
 </tr>
  <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestChannelsRange('getChannelsValues', 'chUniIdx', 'chDMXaddr', 'chRange');">getChannelsValues</div>
    Universe index:<input id="chUniIdx" type="text" value="1">
    DMX start address:<input id="chDMXaddr" type="text" value="1">
    Channels count:<input id="chRange" type="text" value="16">
  </td>
  <td>Retrieve the specified number of DMX values for the given universe, starting at the given address.
      Note that indices start from 1 and not from 0.</td>
  <td><div id="requestChannelsRangeBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>

<!-- ############## Functions API tests ####################### -->
 
 <tr>
  <td colspan="3" align="center"><b>Function APIs</b></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getFunctionsNumber');">getFunctionsNumber</div></td>
  <td>Retrieve the number of functions loaded</td>
  <td><div id="getFunctionsNumberBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getFunctionsList');">getFunctionsList</div></td>
  <td>Retrieve the list of functions with their ID and name</td>
  <td><div id="getFunctionsListBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getFunctionType', 'fTypeID');">getFunctionType</div>
    Function ID:<input id="fTypeID" type="text" value="0">
  </td>
  <td>Retrieve the type of a function with the given ID</td>
  <td><div id="getFunctionTypeBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getFunctionStatus', 'fStatusID');">getFunctionStatus</div>
    Function ID:<input id="fStatusID" type="text" value="0">
  </td>
  <td>Retrieve the status of a function with the given ID. Possible values are "Running", "Stopped" and "Undefined"</td>
  <td><div id="getFunctionStatusBox" class="resultBox"></div></td>
  </tr>
  
<!-- ############## Widgets API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>Virtual Console Widget APIs</b></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getWidgetsNumber');">getWidgetsNumber</div></td>
  <td>Retrieve the number of widgets loaded</td>
  <td><div id="getWidgetsNumberBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getWidgetsList');">getWidgetsList</div></td>
  <td>Retrieve the list of Virtual Console Widgets with their ID and name</td>
  <td><div id="getWidgetsListBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getWidgetType', 'wTypeID');">getWidgetType</div>
    Widget ID:<input id="wTypeID" type="text" value="0">
  </td>
  <td>Retrieve the type of a Virtual Console Widget with the given ID</td>
  <td><div id="getWidgetTypeBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getWidgetStatus', 'wStatusID');">getWidgetStatus</div>
    Widget ID:<input id="wStatusID" type="text" value="0">
  </td>
  <td>Retrieve the status of a Virtual Console Widget with the given ID</td>
  <td><div id="getWidgetStatusBox" class="resultBox"></div></td>
 </tr>
 
<!-- ############## High rate API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>High rate APIs</b></td>
 </tr>
 <tr>
  <td colspan="3">Due to the nature of some type of transmissions (for example a slider changing rapidly),
                  there are a few WebSocket operations stripped down to avoid useless overhead of data.<br>
                  So, instead of transmitting every time the "QLC+API|API name" information, direct calls
                  are here used to accomplish fast operations.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:setSimpleDeskChannel('sdDMXAddress', 'sdDMXValue');">Simple Desk channel set</div>

   Absolute DMX address:<input id="sdDMXAddress" type="text" value="1">
   Value:<input id="sdDMXValue" type="text" value="100">
  </td>
  <td colspan="2">
   This API sets the value of a single channel of the QLC+ Simple Desk. The parameters to send are:<br>
   <b>Absolute DMX address</b>: this is the address of the DMX channel you want to set. It is absolute in the sense
   that the universe information is implicit in the address itself. So for example addresses on the first
   universe will range from 1 to 512, while addresses on the second universe will range from 513 to 1024,
   and so on.<br>
   <b>Value</b>: the value of the DMX channel to set in a range from 0 to 255.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcWidgetSetValue('basicWidgetID', 'basicWidgetValue');">Basic widget value set</div>

   Widget ID:<input id="basicWidgetID" type="text" value="0">
   Value:<input id="basicWidgetValue" type="text" value="255">
  </td>
  <td colspan="2">
    This API is the direct way to set a Virtual Console widget value. It can be used for Buttons, Sliders and
    Audio Triggers. The value to set depends on the widget type itself. Buttons and Audio triggers will only
    support values 0 (= off) and 255 (= on) while Sliders will accept all the values in the 0-255 range.
  </td>
 </tr>
 
 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcCueListControl('clWidgetID', 'clOperation', 'clStep');">Cue list control</div>

   Cue List ID:<input id="clWidgetID" type="text" value="0">
   Operation:<input id="clOperation" type="text" value="PLAY">
   Step (optional):<input id="clStep" type="text" value="1">
  </td>
  <td colspan="2">
    This API demonstrates how to control a Virtual Console Cue List widget. The parameters to be used are:<br>
    <b>Cue List ID</b>: The Cue List widget ID as retrieved with the 'getWidgetsList' API<br>
    <b>Operation</b>: The Cue List operation to perform. Possible values are 'PLAY', 'NEXT', 'PREV' and 'STEP'.
    Only the 'STEP' operation requires a third parameter. The 'PLAY' operation will stop the Cue List if called
    twice.<br>
    <b>Step</b>: The Cue List step index to play. Index starts from 0.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcFrameControl('frWidgetID', 'frOperation');">Multipage frame control</div>

   Frame ID:<input id="frWidgetID" type="text" value="0">
   Operation:<input id="frOperation" type="text" value="NEXT_PG">
  </td>
  <td colspan="2">
    This API demonstrates how to change page of a Virtual Console Frame widget in multipage mode. 
    The parameters to be used are:<br>
    <b>Frame ID</b>: The Frame widget ID as retrieved with the 'getWidgetsList' API<br>
    <b>Operation</b>: The Frame operation to perform. Accepted values are 'NEXT_PG' and 'PREV_PG'.
  </td>
 </tr>

</table>

</body>
</html>
Reply With Quote
  #6  
Old February 14th, 2017, 10:20 PM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
This is the source info from the WEB API

Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<script language="javascript" type="text/javascript">

// the WebSocket instance
var websocket;
var isConnected = false;
// the websocket host location
var wshost = "http://127.0.0.1:9999";

// helper function to send QLC+ API commands
function requestAPI(cmd) 
{
  if (isConnected == true)
    websocket.send("QLC+API|" + cmd);
  else
    alert("You must connect to QLC+ WebSocket first !");
}

// helper function to send a QLC+ API with one parameter.
// The specified parameter is not a value, but a CSS object
// from which a value is retrieved (usually a <input> box)
function requestAPIWithParam(cmd, paramObjName) 
{
  var obj = document.getElementById(paramObjName);
  if (obj)
  {
    if (isConnected == true)
      websocket.send("QLC+API|" + cmd + "|" + obj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function requestChannelsRange(cmd, uniObjName, addressObjName, rangeObjName) 
{
  var uniObj = document.getElementById(uniObjName);
  var addrObj = document.getElementById(addressObjName);
  var rangeObj = document.getElementById(rangeObjName);
  if (uniObj && addrObj && rangeObj)
  {
    if (isConnected == true)
      websocket.send("QLC+API|" + cmd + "|" + uniObj.value + "|" + addrObj.value + "|" + rangeObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function setSimpleDeskChannel(addressObjName, channelValueObjName)
{
  var addrObj = document.getElementById(addressObjName);
  var valObj = document.getElementById(channelValueObjName);
  if (addrObj && valObj)
  {
    if (isConnected == true)
      websocket.send("CH|" + addrObj.value + "|" + valObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function vcWidgetSetValue(wIDObjName, wValueObjName)
{
  var wObj = document.getElementById(wIDObjName);
  var valObj = document.getElementById(wValueObjName);
  if (wObj && valObj)
  {
    if (isConnected == true)
      websocket.send(wObj.value + "|" + valObj.value);
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function vcCueListControl(clIDObjName, clOpObjName, clStepObjName)
{
  var clObj = document.getElementById(clIDObjName);
  var opObj = document.getElementById(clOpObjName);
  var stepObj = document.getElementById(clStepObjName);
  if (clObj && opObj)
  {
    if (isConnected == true)
    {
      if (opObj.value == "STEP")
        websocket.send(clObj.value + "|" + opObj.value + "|" + stepObj.value);
      else
        websocket.send(clObj.value + "|" + opObj.value);
    }
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function vcFrameControl(frIDObjName, frOperation)
{
  var frObj = document.getElementById(frIDObjName);
  var opObj = document.getElementById(frOperation);

  if (frObj && opObj)
  {
    if (isConnected == true)
    {
        websocket.send(frObj.value + "|" + opObj.value);
    }
    else
      alert("You must connect to QLC+ WebSocket first !");
  }
}

function connectToWebSocket(host) {
  var url = 'ws://' + host + '/qlcplusWS';
  websocket = new WebSocket(url);
  // update the host information
  wshost = "http://" + host;

  websocket.onopen = function(ev) {
    //alert("QLC+ connection successful");
    document.getElementById('connStatus').innerHTML = "<font color=green>Connected</font>";
    isConnected = true;
  };

  websocket.onclose = function(ev) {
    alert("QLC+ connection lost !");
  };

  websocket.onerror = function(ev) {
    alert("QLC+ connection error!");
  };
 
  // WebSocket message handler. This is where async events
  // will be shown or processed as needed
  websocket.onmessage = function(ev) {
    // Uncomment the following line to display the received message
    //alert(ev.data);

    // Event data is formatted as follows: "QLC+API|API name|arguments"
    // Arguments vary depending on the API called

    var msgParams = ev.data.split('|');
    
    if (msgParams[0] == "QLC+API")
    {
      if (msgParams[1] == "getFunctionsNumber")
	document.getElementById('getFunctionsNumberBox').innerHTML = msgParams[2];
      
      // Arguments is an array formatted as follows: 
      // Function ID|Function name|Function ID|Function name|...
      else if (msgParams[1] == "getFunctionsList")
      {
	var tableCode = "<table class='apiTable'><tr><th>ID</th><th>Name</th></tr>";
	for (i = 2; i < msgParams.length; i+=2)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('getFunctionsListBox').innerHTML = tableCode;
      }

      else if (msgParams[1] == "getFunctionType")
	document.getElementById('getFunctionTypeBox').innerHTML = msgParams[2];

      else if (msgParams[1] == "getFunctionStatus")
	document.getElementById('getFunctionStatusBox').innerHTML = msgParams[2];

      else if (msgParams[1] == "getWidgetsNumber")
	document.getElementById('getWidgetsNumberBox').innerHTML = msgParams[2];
      
      // Arguments is an array formatted as follows: 
      // Widget ID|Widget name|Widget ID|Widget name|...
      else if (msgParams[1] == "getWidgetsList")
      {
	var tableCode = "<table class='apiTable'><tr><th>ID</th><th>Name</th></tr>";
	for (i = 2; i < msgParams.length; i+=2)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('getWidgetsListBox').innerHTML = tableCode;
      }
      
      else if (msgParams[1] == "getWidgetType")
	document.getElementById('getWidgetTypeBox').innerHTML = msgParams[2];
	
      else if (msgParams[1] == "getWidgetStatus")
      {
	var status = msgParams[2];
	if (msgParams[2] == "PLAY")
	  status = msgParams[2] + "(Step: " + msgParams[3] + ")";
	document.getElementById('getWidgetStatusBox').innerHTML = status;
      }
      
      else if (msgParams[1] == "getChannelsValues")
      {
	var tableCode = "<table class='apiTable'><tr><th>Index</th><th>Value</th><th>Type</th></tr>";
	for (i = 2; i < msgParams.length; i+=3)
	{
	  tableCode = tableCode + "<tr><td>" + msgParams[i] + "</td><td>" + msgParams[i + 1] + "</td><td>" + msgParams[i + 2] + "</td></tr>";
	}
	tableCode += "</table>";
	document.getElementById('requestChannelsRangeBox').innerHTML = tableCode;
      }
    }
  };
};

function loadProject () {
  var formAction = wshost + "/loadProject";
  document.getElementById('lpForm').action = formAction;
}

</script>

<style>

body { 
  background-color: #45484d;
  color: white;
  font:normal 18px/1.2em sans-serif;
}

iframe {
  position: absolute;
  display: block;

  height: 100%;
  width: 100%;

  -moz-border-radius: 12px;
  -webkit-border-radius: 12px; 
  border-radius: 12px; 

  -moz-box-shadow: 4px 4px 14px #000; 
  -webkit-box-shadow: 4px 4px 14px #000; 
  box-shadow: 4px 4px 14px #000; 
}

#prjBox {
  position: absolute;
  width: 50%;
  height: 70%;
  margin-top: 0px;
  margin-left: 47%;
}

.apiTable {
  border-collapse: collapse;
}

.apiTable th {
  font-size: 18px;
  color: white;
  border: solid 1px white;
}

.apiTable tr {
  font-size: 14px; 
  border: solid 1px white;
}

.apiTable td {
  border: solid 1px white;
  padding: 2px 5px 2px 5px;
  margin: 0 5px 0 5px;
}

.apiButton {
  display: table-cell; 
  vertical-align: middle;
  text-align: center;
  color: black;
  cursor:pointer;
  height: 30px;
  padding: 0 10px 0 10px;
  background: #4477a1;
  background: -webkit-gradient(linear, left top, left bottom, from(#81a8cb), to(#4477a1) );
  background: -moz-linear-gradient(-90deg, #81a8cb, #4477a1);

  -moz-border-radius: 6px;
  -webkit-border-radius: 6px; 
  border-radius: 6px; 
}

.apiButton:hover {
  background: #81a8cb;
  background: -webkit-gradient(linear, left top, left bottom, from(#4477a1), to(#81a8cb) );
  background: -moz-linear-gradient(-90deg, #4477a1, #81a8cb);
}

.resultBox {
  display: table-cell;
  vertical-align: middle;
  text-align: center;
  color: #000;
  width: 150px;
  height: 30px;
  background-color: #aaaaaa;
  border-radius: 6px; 
}

</style>

<body>

<h2>Q Light Controller+ Web API test page</h2>

<!-- ############## Project box to display what QLC+ is doing ####################### -->
<div id="prjBox"><iframe name="projectFrame" src="" id="projectFrame"></iframe></div>

<!-- ############## Websocket connection code ####################### -->
QLC+ IP: 
<input type="text" id="qlcplusIP" value="127.0.0.1:9999"></input>
<input type="button" value="Connect" onclick="javascript:connectToWebSocket(document.getElementById('qlcplusIP').value);"></input>
<div id="connStatus" style="display: inline-block;"><font color=red>Not connected</font></div>
<br><br>

<!-- ############## Project load code ####################### -->
<form id="lpForm" onsubmit="loadProject()" method="POST" enctype="multipart/form-data" target="projectFrame">
Load a project:
<input id="loadTrigger" type="file" onchange="document.getElementById('submitTrigger').click();" name="qlcprj" />
<input id="submitTrigger" type="submit" />
</form>
<br><br>

<!-- ############## Individual API tests ####################### -->

<table class="apiTable" width=45%>
 <tr>
  <th width=30%><b>API Function</b></th>
  <th width=30%><b>Description</b></th>
  <th width=40%><b>Result</b></th>
 </tr>
 
<!-- ############## Channels API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>Channels APIs</b></td>
 </tr>
  <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestChannelsRange('getChannelsValues', 'chUniIdx', 'chDMXaddr', 'chRange');">getChannelsValues</div>
    Universe index:<input id="chUniIdx" type="input" value="1"></input>
    DMX start address:<input id="chDMXaddr" type="input" value="1"></input>
    Channels count:<input id="chRange" type="input" value="16"></input>
  </td>
  <td>Retrieve the specified number of DMX values for the given universe, starting at the given address.
      Note that indices start from 1 and not from 0.</td>
  <td><div id="requestChannelsRangeBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>

<!-- ############## Functions API tests ####################### -->
 
 <tr>
  <td colspan="3" align="center"><b>Function APIs</b></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getFunctionsNumber');">getFunctionsNumber</div></td>
  <td>Retrieve the number of functions loaded</td>
  <td><div id="getFunctionsNumberBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getFunctionsList');">getFunctionsList</div></td>
  <td>Retrieve the list of functions with their ID and name</td>
  <td><div id="getFunctionsListBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getFunctionType', 'fTypeID');">getFunctionType</div>
    Function ID:<input id="fTypeID" type="input" value="0"></input>
  </td>
  <td>Retrieve the type of a function with the given ID</td>
  <td><div id="getFunctionTypeBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getFunctionStatus', 'fStatusID');">getFunctionStatus</div>
    Function ID:<input id="fStatusID" type="input" value="0"></input>
  </td>
  <td>Retrieve the status of a function with the given ID. Possible values are "Running", "Stopped" and "Undefined"</td>
  <td><div id="getFunctionStatusBox" class="resultBox"></div></td>
  </tr>
  
<!-- ############## Widgets API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>Virtual Console Widget APIs</b></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getWidgetsNumber');">getWidgetsNumber</div></td>
  <td>Retrieve the number of widgets loaded</td>
  <td><div id="getWidgetsNumberBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td><div class="apiButton" onclick="javascript:requestAPI('getWidgetsList');">getWidgetsList</div></td>
  <td>Retrieve the list of Virtual Console Widgets with their ID and name</td>
  <td><div id="getWidgetsListBox" style="height: 150px; overflow-y: scroll;"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getWidgetType', 'wTypeID');">getWidgetType</div>
    Widget ID:<input id="wTypeID" type="input" value="0"></input>
  </td>
  <td>Retrieve the type of a Virtual Console Widget with the given ID</td>
  <td><div id="getWidgetTypeBox" class="resultBox"></div></td>
 </tr>
 <tr>
  <td>
    <div class="apiButton" onclick="javascript:requestAPIWithParam('getWidgetStatus', 'wStatusID');">getWidgetStatus</div>
    Widget ID:<input id="wStatusID" type="input" value="0"></input>
  </td>
  <td>Retrieve the status of a Virtual Console Widget with the given ID</td>
  <td><div id="getWidgetStatusBox" class="resultBox"></div></td>
 </tr>
 
<!-- ############## High rate API tests ####################### -->

 <tr>
  <td colspan="3" align="center"><b>High rate APIs</b></td>
 </tr>
 <tr>
  <td colspan="3">Due to the nature of some type of transmissions (for example a slider changing rapidly),
                  there are a few WebSocket operations stripped down to avoid useless overhead of data.<br>
                  So, instead of transmitting every time the "QLC+API|API name" information, direct calls
                  are here used to accomplish fast operations.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:setSimpleDeskChannel('sdDMXAddress', 'sdDMXValue');">Simple Desk channel set</div>

   Absolute DMX address:<input id="sdDMXAddress" type="input" value="1"></input>
   Value:<input id="sdDMXValue" type="input" value="100"></input>
  </td>
  <td colspan="2">
   This API sets the value of a single channel of the QLC+ Simple Desk. The parameters to send are:<br>
   <b>Absolute DMX address</b>: this is the address of the DMX channel you want to set. It is absolute in the sense
   that the universe information is implicit in the address itself. So for example addresses on the first
   universe will range from 1 to 512, while addresses on the second universe will range from 513 to 1024,
   and so on.<br>
   <b>Value</b>: the value of the DMX channel to set in a range from 0 to 255.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcWidgetSetValue('basicWidgetID', 'basicWidgetValue');">Basic widget value set</div>

   Widget ID:<input id="basicWidgetID" type="input" value="0"></input>
   Value:<input id="basicWidgetValue" type="input" value="255"></input>
  </td>
  <td colspan="2">
    This API is the direct way to set a Virtual Console widget value. It can be used for Buttons, Sliders and
    Audio Triggers. The value to set depends on the widget type itself. Buttons and Audio triggers will only
    support values 0 (= off) and 255 (= on) while Sliders will accept all the values in the 0-255 range.
  </td>
 </tr>
 
 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcCueListControl('clWidgetID', 'clOperation', 'clStep');">Cue list control</div>

   Cue List ID:<input id="clWidgetID" type="input" value="0"></input>
   Operation:<input id="clOperation" type="input" value="PLAY"></input>
   Step (optional):<input id="clStep" type="input" value="1"></input>
  </td>
  <td colspan="2">
    This API demonstrates how to control a Virtual Console Cue List widget. The parameters to be used are:<br>
    <b>Cue List ID</b>: The Cue List widget ID as retrieved with the 'getWidgetsList' API<br>
    <b>Operation</b>: The Cue List operation to perform. Possible values are 'PLAY', 'NEXT', 'PREV' and 'STEP'.
    Only the 'STEP' operation requires a third parameter. The 'PLAY' operation will stop the Cue List if called
    twice.<br>
    <b>Step</b>: The Cue List step index to play. Index starts from 0.
  </td>
 </tr>

 <tr>
  <td>
   <div class="apiButton" onclick="javascript:vcFrameControl('frWidgetID', 'frOperation');">Multipage frame control</div>

   Frame ID:<input id="frWidgetID" type="input" value="0"></input>
   Operation:<input id="frOperation" type="input" value="NEXT_PG"></input>
  </td>
  <td colspan="2">
    This API demonstrates how to change page of a Virtual Console Frame widget in multipage mode. 
    The parameters to be used are:<br>
    <b>Frame ID</b>: The Frame widget ID as retrieved with the 'getWidgetsList' API<br>
    <b>Operation</b>: The Frame operation to perform. Accepted values are 'NEXT_PG' and 'PREV_PG'.
  </td>
 </tr>

</table>

</body>
</html>


Code:
<!DOCTYPE html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" >
<title>QLC+ Webaccess</title>
<link href="common.css" rel="stylesheet" type="text/css" media="screen">
<link href="virtualconsole.css" rel="stylesheet" type="text/css" media="screen">
<script type="text/javascript" src="websocket.js"></script>
<script type="text/javascript" src="virtualconsole.js"></script>
<script type="text/javascript">
framesWidth[0] = 590;
framesHeight[0] = 270;
framesWidth[1] = 190;
framesHeight[1] = 100;
framesWidth[7] = 650;
framesHeight[7] = 330;
framesWidth[8] = 250;
framesHeight[8] = 280;
framesWidth[27] = 1080;
framesHeight[27] = 865;

</script>
</head>
<body>
<form action="/loadProject" method="POST" enctype="multipart/form-data">
<input id="loadTrigger" type="file" onchange="document.getElementById('submitTrigger').click();" name="qlcprj" />
<input id="submitTrigger" type="submit"/>
</form>
<div class="controlBar">
<a class="button button-blue" href="javascript:document.getElementById('loadTrigger').click();">
<span>Load project</span></a>
<a class="button button-blue" href="/simpleDesk"><span>Simple Desk</span></a>
<a class="button button-blue" href="/config"><span>Configuration</span></a>
<div class="swInfo">Q Light Controller Plus 4.10.5b</div></div>
<div style="position: relative; width: 1920px; height: 1080px; background-color: #f0f0f0;">
<div class="vcframe" id="fr0" style="left: 1330px; top: 0px; width: 590px; height: 270px; background-color: #f0f0f0; border: 1px solid #5a5a5a;">
<a class="vcframeButton" style="position: absolute; left: 0; z-index: 1;" href="javascript:frameToggleCollapse(0);"><img src="expand.png" width="27"></a>
<div class="vcframeHeader" style="color:#ffffff;"><div class="vcFrameText">Primary colours - Generic RGB</div></div>
<div class="vcsoloframe" id="fr1" style="left: 10px; top: 40px; width: 190px; height: 100px; background-color: #f0f0f0; border: 1px solid #ff0000;">
<a class="vcframeButton" style="position: absolute; left: 0; z-index: 1;" href="javascript:frameToggleCollapse(1);"><img src="expand.png" width="27"></a>
<div class="vcsoloframeHeader" style="color:#ffffff;"><div class="vcFrameText">Presets solo frame</div></div>
<div class="vcbutton-wrapper" style="left: 10px; top: 40px;">
<a class="vcbutton" id="2" href="javascript:buttonClick(2);" style="width: 50px; height: 50px; color: #000000; background-color: #ff0000; ">Red scene</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 40px;">
<a class="vcbutton" id="3" href="javascript:buttonClick(3);" style="width: 50px; height: 50px; color: #000000; background-color: #00ff00; ">Green scene</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 40px;">
<a class="vcbutton" id="4" href="javascript:buttonClick(4);" style="width: 50px; height: 50px; color: #000000; background-color: #0000ff; ">Blue scene</a>
</div>
</div>
<div id="5" class="vccuelist" style="left: 210px; top: 40px; width: 300px; height: 220px; background-color: #f0f0f0;">
<div style="width: 100%; height: 186px; overflow: scroll;" >
<table class="hovertable" style="width: 100%;">
<tr><th>#</th><th>Name</th><th>Fade In</th><th>Fade Out</th><th>Duration</th><th>Notes</th></tr>
<tr id="5_0" onclick="enableCue(5, 0);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(5, 0);">
<td>1</td><td>Red scene - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="5_1" onclick="enableCue(5, 1);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(5, 1);">
<td>2</td><td>Green scene - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="5_2" onclick="enableCue(5, 2);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(5, 2);">
<td>3</td><td>Blue scene - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
</table>
</div>
<a class="vccuelistButton" id="play5" href="javascript:sendCueCmd(5, 'PLAY');">
<img src="player_play.png" width="27"></a>
<a class="vccuelistButton" id="stop5" href="javascript:sendCueCmd(5, 'STOP');">
<img src="player_stop.png" width="27"></a>
<a class="vccuelistButton" href="javascript:sendCueCmd(5, 'PREV');">
<img src="back.png" width="27"></a>
<a class="vccuelistButton" href="javascript:sendCueCmd(5, 'NEXT');">
<img src="forward.png" width="27"></a>
</div>
<div class="vcslider" style="left: 520px; top: 40px; width: 60px; height: 200px; background-color: #f0f0f0;">
<div id="slv6" class="vcslLabel" style="top:0px;">0</div>
<input type="range" class="vVertical" id="6" oninput="slVchange(6);" ontouchmove="slVchange(6);" style="width: 150px; margin-top: 150px; margin-left: 30px;" min="0" max="255" step="1" value="0">
<div id="sln6" class="vcslLabel" style="bottom:0px;">Click & Go RGB</div>
</div>
</div>
<div class="vcframe" id="fr7" style="left: 1265px; top: 290px; width: 650px; height: 330px; background-color: #f0f0f0; border: 1px solid #5a5a5a;">
<a class="vcframeButton" style="position: absolute; left: 0; z-index: 1;" href="javascript:frameToggleCollapse(7);"><img src="expand.png" width="27"></a>
<div class="vcframeHeader" style="color:#ffffff;"><div class="vcFrameText">16 Colours - Generic RGB</div></div>
<div class="vcsoloframe" id="fr8" style="left: 10px; top: 40px; width: 250px; height: 280px; background-color: #f0f0f0; border: 1px solid #ff0000;">
<a class="vcframeButton" style="position: absolute; left: 0; z-index: 1;" href="javascript:frameToggleCollapse(8);"><img src="expand.png" width="27"></a>
<div class="vcsoloframeHeader" style="color:#ffffff;"><div class="vcFrameText">Presets solo frame</div></div>
<div class="vcbutton-wrapper" style="left: 70px; top: 40px;">
<a class="vcbutton" id="10" href="javascript:buttonClick(10);" style="width: 50px; height: 50px; color: #000000; background-color: #000080; ">Scene Dark Blue</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 40px;">
<a class="vcbutton" id="11" href="javascript:buttonClick(11);" style="width: 50px; height: 50px; color: #000000; background-color: #0000ff; ">Scene Blue</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 40px;">
<a class="vcbutton" id="12" href="javascript:buttonClick(12);" style="width: 50px; height: 50px; color: #000000; background-color: #008000; ">Scene Dark Green</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 100px;">
<a class="vcbutton" id="13" href="javascript:buttonClick(13);" style="width: 50px; height: 50px; color: #000000; background-color: #008080; ">Scene Dark Cyan</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 100px;">
<a class="vcbutton" id="14" href="javascript:buttonClick(14);" style="width: 50px; height: 50px; color: #000000; background-color: #00ff00; ">Scene Green</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 100px;">
<a class="vcbutton" id="15" href="javascript:buttonClick(15);" style="width: 50px; height: 50px; color: #000000; background-color: #00ffff; ">Scene Cyan</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 100px;">
<a class="vcbutton" id="16" href="javascript:buttonClick(16);" style="width: 50px; height: 50px; color: #000000; background-color: #800000; ">Scene Dark Red</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 160px;">
<a class="vcbutton" id="17" href="javascript:buttonClick(17);" style="width: 50px; height: 50px; color: #000000; background-color: #800080; ">Scene Dark Magenta</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 160px;">
<a class="vcbutton" id="18" href="javascript:buttonClick(18);" style="width: 50px; height: 50px; color: #000000; background-color: #808000; ">Scene Dark Yellow</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 160px;">
<a class="vcbutton" id="19" href="javascript:buttonClick(19);" style="width: 50px; height: 50px; color: #000000; background-color: #808080; ">Scene Dark Gray</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 160px;">
<a class="vcbutton" id="20" href="javascript:buttonClick(20);" style="width: 50px; height: 50px; color: #000000; background-color: #c0c0c0; ">Scene Light Gray</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 220px;">
<a class="vcbutton" id="21" href="javascript:buttonClick(21);" style="width: 50px; height: 50px; color: #000000; background-color: #ff0000; ">Scene Red</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 220px;">
<a class="vcbutton" id="22" href="javascript:buttonClick(22);" style="width: 50px; height: 50px; color: #000000; background-color: #ff00ff; ">Scene Magenta</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 220px;">
<a class="vcbutton" id="23" href="javascript:buttonClick(23);" style="width: 50px; height: 50px; color: #000000; background-color: #ffff00; ">Scene Yellow</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 220px;">
<a class="vcbutton" id="24" href="javascript:buttonClick(24);" style="width: 50px; height: 50px; color: #000000; background-color: #ffffff; ">Scene White</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 40px;">
<a class="vcbutton" id="9" href="javascript:buttonClick(9);" style="width: 50px; height: 50px; color: #000000; background-color: #000000; ">Scene Black</a>
</div>
</div>
<div id="25" class="vccuelist" style="left: 270px; top: 40px; width: 300px; height: 220px; background-color: #f0f0f0;">
<div style="width: 100%; height: 186px; overflow: scroll;" >
<table class="hovertable" style="width: 100%;">
<tr><th>#</th><th>Name</th><th>Fade In</th><th>Fade Out</th><th>Duration</th><th>Notes</th></tr>
<tr id="25_0" onclick="enableCue(25, 0);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 0);">
<td>1</td><td>Scene Black - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_1" onclick="enableCue(25, 1);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 1);">
<td>2</td><td>Scene Dark Blue - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_2" onclick="enableCue(25, 2);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 2);">
<td>3</td><td>Scene Blue - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_3" onclick="enableCue(25, 3);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 3);">
<td>4</td><td>Scene Dark Green - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_4" onclick="enableCue(25, 4);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 4);">
<td>5</td><td>Scene Dark Cyan - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_5" onclick="enableCue(25, 5);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 5);">
<td>6</td><td>Scene Green - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_6" onclick="enableCue(25, 6);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 6);">
<td>7</td><td>Scene Cyan - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_7" onclick="enableCue(25, 7);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 7);">
<td>8</td><td>Scene Dark Red - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_8" onclick="enableCue(25, 8);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 8);">
<td>9</td><td>Scene Dark Magenta - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_9" onclick="enableCue(25, 9);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 9);">
<td>10</td><td>Scene Dark Yellow - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_10" onclick="enableCue(25, 10);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 10);">
<td>11</td><td>Scene Dark Gray - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_11" onclick="enableCue(25, 11);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 11);">
<td>12</td><td>Scene Light Gray - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_12" onclick="enableCue(25, 12);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 12);">
<td>13</td><td>Scene Red - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_13" onclick="enableCue(25, 13);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 13);">
<td>14</td><td>Scene Magenta - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_14" onclick="enableCue(25, 14);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 14);">
<td>15</td><td>Scene Yellow - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
<tr id="25_15" onclick="enableCue(25, 15);" onmouseover="this.style.backgroundColor='#CCD9FF';" onmouseout="checkMouseOut(25, 15);">
<td>16</td><td>Scene White - Generic RGB</td><td>3s</td><td>0ms</td><td>10s</td><td></td>
</td>
</table>
</div>
<a class="vccuelistButton" id="play25" href="javascript:sendCueCmd(25, 'PLAY');">
<img src="player_play.png" width="27"></a>
<a class="vccuelistButton" id="stop25" href="javascript:sendCueCmd(25, 'STOP');">
<img src="player_stop.png" width="27"></a>
<a class="vccuelistButton" href="javascript:sendCueCmd(25, 'PREV');">
<img src="back.png" width="27"></a>
<a class="vccuelistButton" href="javascript:sendCueCmd(25, 'NEXT');">
<img src="forward.png" width="27"></a>
</div>
<div class="vcslider" style="left: 580px; top: 40px; width: 60px; height: 200px; background-color: #f0f0f0;">
<div id="slv26" class="vcslLabel" style="top:0px;">0</div>
<input type="range" class="vVertical" id="26" oninput="slVchange(26);" ontouchmove="slVchange(26);" style="width: 150px; margin-top: 150px; margin-left: 30px;" min="0" max="255" step="1" value="0">
<div id="sln26" class="vcslLabel" style="bottom:0px;">Click & Go RGB</div>
</div>
</div>
<div class="vcsoloframe" id="fr27" style="left: 180px; top: 10px; width: 1080px; height: 865px; background-color: #f0f0f0; border: 1px solid #ff0000;">
<a class="vcframeButton" style="position: absolute; left: 0; z-index: 1;" href="javascript:frameToggleCollapse(27);"><img src="expand.png" width="27"></a>
<div class="vcsoloframeHeader" style="color:#ffffff;"><div class="vcFrameText">Animations - Generic RGB</div></div>
<div class="vcbutton-wrapper" style="left: 10px; top: 40px;">
<a class="vcbutton" id="28" href="javascript:buttonClick(28);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">abstract</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 40px;">
<a class="vcbutton" id="29" href="javascript:buttonClick(29);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">ocean</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 40px;">
<a class="vcbutton" id="30" href="javascript:buttonClick(30);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">rainbow</a>
</div>
<div class="vcbutton-wrapper" style="left: 280px; top: 55px;">
<a class="vcbutton" id="31" href="javascript:buttonClick(31);" style="width: 300px; height: 255px; color: #000000; background-color: #f0f0f0; border: 3px solid #00E600;">sunset</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 100px;">
<a class="vcbutton" id="32" href="javascript:buttonClick(32);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Warm White</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 100px;">
<a class="vcbutton" id="33" href="javascript:buttonClick(33);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">yellow</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 100px;">
<a class="vcbutton" id="34" href="javascript:buttonClick(34);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">green</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 100px;">
<a class="vcbutton" id="35" href="javascript:buttonClick(35);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">white</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 160px;">
<a class="vcbutton" id="36" href="javascript:buttonClick(36);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Flash test red purple</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 160px;">
<a class="vcbutton" id="37" href="javascript:buttonClick(37);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Random flashing</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 160px;">
<a class="vcbutton" id="38" href="javascript:buttonClick(38);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">random flashing red green</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 160px;">
<a class="vcbutton" id="39" href="javascript:buttonClick(39);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Opposite</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 220px;">
<a class="vcbutton" id="40" href="javascript:buttonClick(40);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Plasma</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 220px;">
<a class="vcbutton" id="41" href="javascript:buttonClick(41);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Plasma (Colors)</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 220px;">
<a class="vcbutton" id="42" href="javascript:buttonClick(42);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Column</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 220px;">
<a class="vcbutton" id="43" href="javascript:buttonClick(43);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Fill Column</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 280px;">
<a class="vcbutton" id="44" href="javascript:buttonClick(44);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Fill Row</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 280px;">
<a class="vcbutton" id="45" href="javascript:buttonClick(45);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Fill Single</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 280px;">
<a class="vcbutton" id="46" href="javascript:buttonClick(46);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Row</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 280px;">
<a class="vcbutton" id="47" href="javascript:buttonClick(47);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Random Single</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 340px;">
<a class="vcbutton" id="48" href="javascript:buttonClick(48);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Squares</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 340px;">
<a class="vcbutton" id="49" href="javascript:buttonClick(49);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Squares From Center</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 340px;">
<a class="vcbutton" id="50" href="javascript:buttonClick(50);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Stripes</a>
</div>
<div class="vcbutton-wrapper" style="left: 190px; top: 340px;">
<a class="vcbutton" id="51" href="javascript:buttonClick(51);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Stripes From Center</a>
</div>
<div class="vcbutton-wrapper" style="left: 10px; top: 400px;">
<a class="vcbutton" id="52" href="javascript:buttonClick(52);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Strobe</a>
</div>
<div class="vcbutton-wrapper" style="left: 70px; top: 400px;">
<a class="vcbutton" id="53" href="javascript:buttonClick(53);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Vertical fall</a>
</div>
<div class="vcbutton-wrapper" style="left: 130px; top: 400px;">
<a class="vcbutton" id="54" href="javascript:buttonClick(54);" style="width: 50px; height: 50px; color: #000000; background-color: #f0f0f0; ">Animation Waves</a>
</div>
<div class="vcbutton-wrapper" style="left: 720px; top: 65px;">
<a class="vcbutton" id="55" href="javascript:buttonClick(55);" style="width: 295px; height: 230px; color: #000000; background-color: #000000; ">Scene Black</a>
</div>
</div>
</div>
</body>
</html>

Last edited by shirec; February 15th, 2017 at 07:52 AM. Reason: updated source list
Reply With Quote
  #7  
Old February 15th, 2017, 07:44 AM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
Im sure it's close to this.. but not this.

It has to be close to this but its saying its expecting more information. I am sure this is not enough to send a command and am missing something... The above code says a websocket must be opened first...


Code:
dim s
const server_url = "192.168.0.2:9999"
const headers="Content-Type: text/html; charset=utf-8"  

s = hs.URLAction(server_url, "POST", input id="31", type="text", value="0", headers)
Reply With Quote
  #8  
Old February 15th, 2017, 09:22 AM
sparkman's Avatar
sparkman sparkman is offline
OverSeer
 
Join Date: Oct 2001
Location: Calgary, Alberta, Canada
Posts: 6,007
Looks like the webpage references a websocket.js file. Take a look at it as it may give more info as to what it's doing on the backend.

Cheers
Al
Reply With Quote
  #9  
Old February 15th, 2017, 11:31 AM
mrhappy mrhappy is offline
OverSeer
 
Join Date: Nov 2007
Location: W.Mids, UK
Posts: 7,085
I'd personally look if at all possible away from websockets which this appears to use, theres no native support built into HS for them (they are a protocol in there own right). Whilst there is a System.Net.Sockets namespace that only works with .net 4.5 and HS is written for .net 4.0 so they won't work out of the box. I'd approach the QLight people and see if they have a HTTP API...
Reply With Quote
  #10  
Old February 15th, 2017, 08:37 PM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
I just asked if they have a http API in there forum. Its a free program not a paid one so I am going to assume there is no http API and nobody will go out of there way to make it happen.
.
This is unfortunate as my garden lights are controlled by DMX. Does anyone have any recommendations for dmx controlled lighting which can be affected by Homeseer.
.
Maby I will try and find a program similar to Qlight that does support http API? Or does Homeseer support DMX natively? (Through E1.31 protocol?)
.
I am after any solution to get the lights working. It needs to be more than just solid colours tho.
.
Thanks
Reply With Quote
  #11  
Old February 16th, 2017, 12:24 PM
mrhappy mrhappy is offline
OverSeer
 
Join Date: Nov 2007
Location: W.Mids, UK
Posts: 7,085
Quote:
Originally Posted by shirec View Post
I just asked if they have a http API in there forum. Its a free program not a paid one so I am going to assume there is no http API and nobody will go out of there way to make it happen.
.
This is unfortunate as my garden lights are controlled by DMX. Does anyone have any recommendations for dmx controlled lighting which can be affected by Homeseer.
.
Maby I will try and find a program similar to Qlight that does support http API? Or does Homeseer support DMX natively? (Through E1.31 protocol?)
.
I am after any solution to get the lights working. It needs to be more than just solid colours tho.
.
Thanks
Have you seen this - https://forums.homeseer.com/showthread.php?t=184921 - I used FreeStyler and control it from HS script.
Reply With Quote
  #12  
Old February 17th, 2017, 04:14 AM
shirec's Avatar
shirec shirec is offline
Seer
 
Join Date: Oct 2016
Location: Australia
Posts: 14
Appreciate that. If I can get it to do some simple rgb colour wave then it would definitely work. I will look into it very soon! Sounds good tho. Thanks again!
Reply With Quote
  #13  
Old December 7th, 2017, 06:00 AM
Moskus's Avatar
Moskus Moskus is online now
OverSeer
 
Join Date: Aug 2007
Location: Norway
Posts: 3,643
I'm looking into making a quick HomeSeer plugin for QLC+. Interessted?
__________________
HSPro 3.0.0.368, Z-NET with Z-wave plugin 3.0.1.136, RFXCOM + 2x RFXtrx433E, HSTouch, Squeezebox plugin, iTach IP/WF2IR & GC-100-6 with UltraGCIR, BLDenon, NetcamStudio, Jon00s Webpage builder, Harmony Hub plugin, SCSIP (with FreePBX), Arduino plugin, IFTTT, Pushalot plugin, Device History plugin.
Running on Windows 10 (64) virtualized
on ESXi (Fujitsu Primergy TX150 S8).
WinSeer (for Win10) - TextSeer - FitbitSeer - HSPI_MoskusSample

Are you Norwegian (or Scandinavian) and getting started with HomSeer? Read the "HomeSeer School"!
Reply With Quote
Reply

Bookmarks

Tags
api, post, q light, qlc, qlight

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
EVENT:"Control a Device" Not working, "Send X10" Working cyber_jocky HS3 / HS3PRO Discussion 6 May 1st, 2016 06:05 PM
DSC not working on HS3 Sheriff HomeSeer DSC Plug-in 16 October 8th, 2015 11:31 AM
All working -> switch resets -> nothing working tahl Insteon Plug-in (Mark Sandler) 11 March 9th, 2013 06:42 PM
weather not working.. tips to get it working? purezerg Jon00's plugins and scripts 6 January 26th, 2009 02:26 PM
One LM12 not working through events, while working directly rc-man HomeSeer General Discussion Area 6 February 2nd, 2005 02:32 PM


All times are GMT -4. The time now is 04:41 PM.


Copyright HomeSeer Technologies, LLC