t8100: Initial implementation

This module implements support for the Amphenol Telaire Ventostat
T8100 Ventilation Controller with BACnet interface.  It may also
support the T8200 and T8300 models, but they have not been tested.

The Telaire Ventostat T8100 reports Temperature, Humidity and CO2
concentrations.  It supports an optional relay with a settable trigger
point.  The unit this driver was tested under did not support the
optional relay.  The temperature range supported is 0-50C, humidity is
0-100% non-condensing, and CO2 range is appoximately 0-2000 PPM for
the T8100.  Other sensors in this family support wider ranges.

Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2016-06-10 12:46:49 -06:00
parent 93fea877e3
commit 3c5d498ae5
12 changed files with 1118 additions and 0 deletions

View File

@ -262,6 +262,7 @@ if (BACNET_FOUND)
# we need access to bacnetmstp headers too
include_directories(${PROJECT_SOURCE_DIR}/src/bacnetmstp)
add_example (e50hx)
add_example (t8100)
endif()
add_example (vcap)
add_example (ds2413)

117
examples/c++/t8100.cxx Normal file
View File

@ -0,0 +1,117 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <iostream>
#include <signal.h>
#include "t8100.hpp"
using namespace std;
using namespace upm;
bool shouldRun = true;
void sig_handler(int signo)
{
if (signo == SIGINT)
shouldRun = false;
}
int main(int argc, char **argv)
{
signal(SIGINT, sig_handler);
//! [Interesting]
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
string defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (argc > 1)
defaultDev = string(argv[1]);
cout << "Using device " << defaultDev << endl;
cout << "Initializing..." << endl;
// Instantiate an T8100 object for an T8100 device that has 568000
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
T8100 *sensor = new T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor->initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor->setDebug(true);
cout << endl;
cout << "Device Description: " << sensor->getDeviceDescription() << endl;
cout << "Device Location: " << sensor->getDeviceLocation() << endl;
cout << endl;
// update and print a few values every 5 seconds
while (shouldRun)
{
// update our values
sensor->update();
cout << "CO2 Concentration: "
<< sensor->getCO2()
<< " ppm"
<< endl;
// we show both C and F for temperature
cout << "Temperature: " << sensor->getTemperature()
<< " C / "
<< sensor->getTemperature(true)
<< " F"
<< endl;
cout << "Humidity: " << sensor->getHumidity()
<< " %RH"
<< endl;
cout << "Relay State: " << sensor->getRelayState()
<< endl;
cout << endl;
sleep(5);
}
cout << "Exiting..." << endl;
delete sensor;
//! [Interesting]
return 0;
}

View File

@ -124,6 +124,7 @@ if (MODBUS_FOUND)
endif()
if (BACNET_FOUND)
add_example(E50HX_Example e50hx)
add_example(T8100_Example t8100)
endif()
add_example(VCAP_Example vcap)
add_example(BMP280_Example bmp280)

View File

@ -0,0 +1,97 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
import upm_t8100.T8100;
public class T8100_Example
{
private static String defaultDev = "/dev/ttyUSB0";
public static void main(String[] args) throws InterruptedException
{
// ! [Interesting]
// You will need to edit this example to conform to your site
// and your devices, specifically the Device Object Instance
// ID passed to the constructor, and the arguments to
// initMaster() that are appropriate for your BACnet network.
if (args.length > 0)
defaultDev = args[0];
System.out.println("Using device " + defaultDev);
System.out.println("Initializing...");
// Instantiate an T8100 object for an T8100 device that has
// 568000 as it's unique Device Object Instance ID. NOTE: You
// will certainly want to change this to the correct value for
// your device(s).
T8100 sensor = new T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001
// as our unique Device Object Instance ID, 2 as our MAC
// address and using default values for maxMaster and
// maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
System.out.println();
System.out.println("Device Description: "
+ sensor.getDeviceDescription());
System.out.println("Device Location: " + sensor.getDeviceLocation());
System.out.println();
// update and print a few values every 5 seconds
while (true)
{
// update our values
sensor.update();
System.out.println("CO2 Concentration: "
+ sensor.getCO2()
+ " ppm");
// we show both C and F for temperature
System.out.println("Temperature: "
+ sensor.getTemperature()
+ " C / "
+ sensor.getTemperature(true)
+ " F");
System.out.println("Humidity: "
+ sensor.getHumidity()
+ " %RH");
System.out.println("Relay State: "
+ sensor.getRelayState());
System.out.println();
Thread.sleep(5000);
}
// ! [Interesting]
}
}

View File

@ -0,0 +1,98 @@
/*jslint node:true, vars:true, bitwise:true, unparam:true */
/*jshint unused:true */
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
var sensorObj = require('jsupm_t8100');
/************** Main code **************/
// You will need to edit this example to conform to your site and your
// devices, specifically the Device Object Instance ID passed to the
// constructor, and the arguments to initMaster() that are
// appropriate for your BACnet network.
var defaultDev = "/dev/ttyUSB0";
// if an argument was specified, use it as the device instead
if (process.argv.length > 2)
{
defaultDev = process.argv[2];
}
console.log("Using device " + defaultDev);
console.log("Initializing...");
// Instantiate an T8100 object for an T8100 device that has 568000
// as it's unique Device Object Instance ID. NOTE: You will
// certainly want to change this to the correct value for your
// device(s).
var sensor = new sensorObj.T8100(568000);
// Initialize our BACnet master, if it has not already been
// initialized, with the device and baudrate, choosing 1000001 as
// our unique Device Object Instance ID, 2 as our MAC address and
// using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2);
// Uncomment to enable debugging output
// sensor.setDebug(true);
console.log("");
console.log("Device Description:", sensor.getDeviceDescription());
console.log("Device Location:", sensor.getDeviceLocation());
console.log("");
// update and print a few values every 5 seconds
setInterval(function()
{
// update our values
sensor.update();
console.log("CO2 Concentration:", sensor.getCO2(), "ppm");
// we show both C and F for temperature
console.log("Temperature:", sensor.getTemperature(),
"C /", sensor.getTemperature(true), "F");
console.log("Humidity:", sensor.getHumidity(), "%RH");
console.log("Relay State:", sensor.getRelayState());
console.log("");
}, 5000);
process.on('SIGINT', function()
{
sensor = null;
sensorObj.cleanUp();
sensorObj = null;
console.log("Exiting...");
process.exit(0);
});

97
examples/python/t8100.py Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# Copyright (c) 2016 Intel Corporation.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
import time, sys, signal, atexit
import pyupm_t8100 as sensorObj
## Exit handlers ##
# This function stops python from printing a stacktrace when you hit control-C
def SIGINTHandler(signum, frame):
raise SystemExit
# This function lets you run code on exit
def exitHandler():
print "Exiting..."
sys.exit(0)
# Register exit handlers
atexit.register(exitHandler)
signal.signal(signal.SIGINT, SIGINTHandler)
# You will need to edit this example to conform to your site and your
# devices, specifically the Device Object Instance ID passed to the
# constructor, and the arguments to initMaster() that are
# appropriate for your BACnet network.
defaultDev = "/dev/ttyUSB0"
# if an argument was specified, use it as the device instead
if (len(sys.argv) > 1):
defaultDev = sys.argv[1]
print "Using device", defaultDev
print "Initializing..."
# Instantiate an T8100 object for an T8100 device that has 568000
# as it's unique Device Object Instance ID. NOTE: You will
# certainly want to change this to the correct value for your
# device(s).
sensor = sensorObj.T8100(568000)
# Initialize our BACnet master, if it has not already been
# initialized, with the device and baudrate, choosing 1000001 as
# our unique Device Object Instance ID, 2 as our MAC address and
# using default values for maxMaster and maxInfoFrames
sensor.initMaster(defaultDev, 38400, 1000001, 2)
# Uncomment to enable debugging output
# sensor.setDebug(True);
# output the serial number and firmware revision
print
print "Device Description:", sensor.getDeviceDescription()
print "Device Location:", sensor.getDeviceLocation()
print
# update and print available values every 5 seconds
while (1):
# update our values
sensor.update();
print "CO2 Concentration:",
print sensor.getCO2(),
print "ppm"
# we show both C and F for temperature
print "Temperature:", sensor.getTemperature(),
print "C /", sensor.getTemperature(True), "F"
print "Humidity:",
print sensor.getHumidity(),
print "%RH"
print "Relay State:",
print sensor.getRelayState()
print
time.sleep(5)

28
src/t8100/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
set (libname "t8100")
set (libdescription "upm module for the Telaire T8100 Ventostat")
set (module_src ${libname}.cxx)
set (module_hpp ${libname}.hpp)
pkg_check_modules(BACNET libbacnet)
if (BACNET_FOUND)
# upm-libbacnetmstp will bring in libbacnet, I hope
set (reqlibname "upm-bacnetmstp")
include_directories(${BACNET_INCLUDE_DIRS})
include_directories("../bacnetmstp")
upm_module_init()
target_link_libraries(${libname} bacnetmstp)
if (BUILDSWIG)
if (BUILDSWIGNODE)
set_target_properties(${SWIG_MODULE_jsupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (jsupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGPYTHON)
set_target_properties(${SWIG_MODULE_pyupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (pyupm_${libname} bacnetmstp)
endif()
if (BUILDSWIGJAVA)
set_target_properties(${SWIG_MODULE_javaupm_${libname}_REAL_NAME} PROPERTIES SKIP_BUILD_RPATH TRUE)
swig_link_libraries (javaupm_${libname} bacnetmstp)
endif()
endif()
endif ()

22
src/t8100/javaupm_t8100.i Normal file
View File

@ -0,0 +1,22 @@
%module javaupm_t8100
%include "../upm.i"
%include "typemaps.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}
%pragma(java) jniclasscode=%{
static {
try {
System.loadLibrary("javaupm_t8100");
} catch (UnsatisfiedLinkError e) {
System.err.println("Native code library failed to load. \n" + e);
System.exit(1);
}
}
%}

10
src/t8100/jsupm_t8100.i Normal file
View File

@ -0,0 +1,10 @@
%module jsupm_t8100
%include "../upm.i"
%include "stdint.i"
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}

14
src/t8100/pyupm_t8100.i Normal file
View File

@ -0,0 +1,14 @@
// Include doxygen-generated documentation
%include "pyupm_doxy2swig.i"
%module pyupm_t8100
%include "../upm.i"
%include "stdint.i"
%feature("autodoc", "3");
%include "bacnetmstp.hpp"
%include "bacnetutil.hpp"
%include "t8100.hpp"
%{
#include "t8100.hpp"
%}

254
src/t8100/t8100.cxx Normal file
View File

@ -0,0 +1,254 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include "t8100.hpp"
using namespace upm;
using namespace std;
// conversion from fahrenheit to celcius and back
static float f2c(float f)
{
return ((f - 32.0) / (9.0 / 5.0));
}
static float c2f(float c)
{
return (c * (9.0 / 5.0) + 32.0);
}
T8100::T8100(uint32_t targetDeviceObjectID) :
BACNETUTIL(targetDeviceObjectID)
{
setDebug(false);
// we disable this by default for performance reasons
checkReliability(false);
m_isTempInitialized = false;
m_isCelcius = false;
m_humidity = 0.0;
m_temperature = 0.0;
m_co2 = 0.0;
m_relayState = false;
}
T8100::~T8100()
{
}
void T8100::update()
{
if (!m_isTempInitialized)
{
// this will update internals so conversions work properly
getTemperatureScale();
}
float tmpF = getAnalogInput(AI_Temperature_Thermistor);
if (m_isCelcius)
m_temperature = tmpF;
else
m_temperature = f2c(tmpF);
m_humidity = getAnalogInput(AI_Relative_Humidity);
m_co2 = getAnalogInput(AI_CO2);
m_relayState = getBinaryInput(BI_Relay_State);
}
float T8100::getTemperature(bool fahrenheit)
{
if (fahrenheit)
return c2f(m_temperature);
else
return m_temperature;
}
void T8100::setTemperatureScale(bool fahrenheit)
{
setBinaryValue(BV_Temperature_Units, fahrenheit);
m_isTempInitialized = true;
m_isCelcius = (fahrenheit) ? false : true;
}
bool T8100::getTemperatureScale()
{
bool scale = getBinaryValue(BV_Temperature_Units);
m_isTempInitialized = true;
m_isCelcius = !scale;
return scale;
}
float T8100::getTemperatureOffset()
{
return getAnalogValue(AV_Temperature_Offset);
}
void T8100::setTemperatureOffset(float value)
{
// Always in C...
if (value < -50.0 || value > 50.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between -50 and 50,"
+ " in degrees Celcius");
}
setAnalogValue(AV_Temperature_Offset, value);
}
float T8100::getHumidityOffset()
{
return getAnalogValue(AV_RH_Offset);
}
void T8100::setHumidityOffset(float value)
{
if (value < -100.0 || value > 100.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between -100 and 100");
}
setAnalogValue(AV_RH_Offset, value);
}
float T8100::getRelaySetPoint()
{
return getAnalogValue(AV_Relay_Set_Point);
}
void T8100::setRelaySetPoint(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Relay_Set_Point, value);
}
float T8100::getRelayHysteresis()
{
return getAnalogValue(AV_Relay_Hysteresis);
}
void T8100::setRelayHysteresis(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Relay_Hysteresis, value);
}
float T8100::getElevation()
{
return getAnalogValue(AV_Elevation);
}
void T8100::setElevation(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Elevation, value);
}
float T8100::getCalibrationSinglePoint()
{
return getAnalogValue(AV_Calibration_Single_Point);
}
void T8100::setCalibrationSinglePoint(float value)
{
if (value < 0.00 || value > 65535.0)
{
throw std::out_of_range(std::string(__FUNCTION__)
+ ": value must be between 0 and 65535");
}
setAnalogValue(AV_Calibration_Single_Point, value);
}
float T8100::getBaudRate()
{
return getAnalogValue(AV_Baud_Rate);
}
float T8100::getMACAddress()
{
return getAnalogValue(AV_MAC_Address);
}
bool T8100::getABCLogicState()
{
return getBinaryValue(BV_ABC_Logic_State);
}
void T8100::setABCLogicState(bool value)
{
setBinaryValue(BV_ABC_Logic_State, value);
}
bool T8100::getABCLogicReset()
{
return getBinaryValue(BV_ABC_Logic_Reset);
}
void T8100::setABCLogicReset(bool value)
{
setBinaryValue(BV_ABC_Logic_Reset, value);
}
bool T8100::getCO2Calibration()
{
return getBinaryValue(BV_CO2_Calibration);
}
void T8100::setCO2Calibration(bool value)
{
setBinaryValue(BV_CO2_Calibration, value);
}

379
src/t8100/t8100.hpp Normal file
View File

@ -0,0 +1,379 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* Copyright (c) 2016 Intel Corporation.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include <string>
#include <map>
#include "bacnetmstp.hpp"
#include "bacnetutil.hpp"
namespace upm {
/**
* @brief Amphenol Telaire Ventostat T8100 Ventilation Controller
* @defgroup t8100 libupm-t8100
* @ingroup uart temp gaseous
*/
/**
* @library t8100
* @sensor t8100
* @comname UPM API for the Amphenol Telaire Ventostat T8100
* Ventilation Controller
* @type gaseous temp
* @man amphenol
* @con uart
* @web https://www.instrumart.com/products/configure/18180?quantity=1
*
* @brief UPM API for the Amphenol Telaire Ventostat T8100
* Ventilation Controller
*
* This module implements support for the Amphenol Telaire Ventostat
* T8100 Ventilation Controller with BACnet interface. It may also
* support the T8200 and T8300 models, but they have not been
* tested.
*
* The Telaire Ventostat T8100 reports Temperature, Humidity and CO2
* concentrations. It supports an optional relay with a settable
* trigger point. The unit this driver was tested under did not
* support the optional relay. The temperature range supported is
* 0-50C, humidity is 0-100% non-condensing, and CO2 range is
* appoximately 0-2000 PPM for the T8100. Other sensors in this
* family support wider ranges.
*
* This module was developed using the upm::BACNETMSTP library,
* based on libbacnet-stack 0.8.3. Both libbacnet 0.8.3 and the
* upm::BACNETMSTP libraries must be present in order to build this
* module.
*
* It was connected using an RS232->RS485 interface. You cannot use
* the built in MCU TTL UART pins for accessing this device -- you
* must use a full Serial RS232->RS485 or USB-RS485 interface
* connected via USB.
*
* @snippet t8100.cxx Interesting
*/
class T8100 : public BACNETUTIL {
public:
// Supported Analog Value Objects. These are readable and writable.
typedef enum : uint32_t {
AV_Temperature_Offset = 1,
AV_RH_Offset = 2,
AV_Relay_Set_Point = 3,
AV_Relay_Hysteresis = 4,
AV_Elevation = 5,
AV_Calibration_Single_Point = 6,
AV_Baud_Rate = 7,
AV_MAC_Address = 8
} ANALOG_VALUES_T;
// Supported Analog Input Objects. These are read only.
typedef enum : uint32_t {
AI_CO2 = 1,
AI_Relative_Humidity = 2,
AI_Temperature_ChipCap = 3,
AI_Temperature_Thermistor = 4
} ANALOG_INPUTS_T;
// Supported Binary Value Objects. These are readable and writable.
typedef enum : uint32_t {
BV_Temperature_Units = 1,
BV_ABC_Logic_State = 2,
BV_ABC_Logic_Reset = 3,
BV_CO2_Calibration = 4
} BINARY_VALUES_T;
// Supported Binary Input Objects. These are read only.
typedef enum : uint32_t {
BI_Relay_State = 1
} BINARY_INPUTS_T;
/**
* T8100 constructor
*
* @param targetDeviceObjectID the unique Instance ID of the
* Device Object. This number is used to uniquely identify
* devices on the BACnet network, and ranges from 1 to 4194302.
* This is not the device's MAC address, though on some devices,
* the MAC address may be used as part of this number. On the
* T8100, this number is 568XXX, where XXX are the 3 digits of the
* set MAC address. The MAC address is configured via DIP switches
* within the device.
*/
T8100(uint32_t targetDeviceObjectID);
/**
* T8100 Destructor
*/
~T8100();
/**
* Read current values from the sensor and update internal stored
* values for temperature, humidity, CO2 concentration and relay
* state. This method must be called prior to querying any
* of the aforementioned values.
*/
void update();
/**
* Get the current relative humidity. update() must have been
* called prior to calling this method.
*
* @return The last humidity reading
*/
float getHumidity()
{
return m_humidity;
}
/**
* Get the current CO2 concentration in Parts per Million (PPM).
* update() must have been called prior to calling this method.
*
* @return The last CO2 reading
*/
float getCO2()
{
return m_co2;
}
/**
* Get the current temperature. update() must have been called
* prior to calling this method.
*
* @param fahrenheit true to return the temperature in degrees
* fahrenheit, false to return the temperature in degrees celcius.
* The default is false (degrees Celcius).
* @return The last temperature reading in Celcius or Fahrenheit.
*/
float getTemperature(bool fahrenheit=false);
/**
* Return the current state of the relay. This function will
* always return false if the relay option is not installed.
* update() must have been called prior to calling this method.
*
* @return true if the relay is active, false if inactive.
*/
bool getRelayState()
{
return m_relayState;
}
/**
* Set the device temperature scale to Celcius of Fahrenheit. For
* devices with an LCD display, this will affect which scale is
* displayed. When changing the scale, it may take several
* seconds for the setting to take effect.
*
* @param fahrenheit true to set the scale to fahrenheit, false
* for celcius.
*/
void setTemperatureScale(bool fahrenheit);
/**
* Get the device temperature scale.
*
* @return true if scale is fahrenheit, false for celcius.
*/
bool getTemperatureScale();
/**
* Get the current temperature offset.
*
* @return The configured temperature offset.
*/
float getTemperatureOffset();
/**
* Set the device temperature offset. The offset is applied by
* the device internally to the temperature reading. The offset
* must always be specified in degrees Celcius. Valid values must
* be between -50 and 50.
*
* @param value The temperature offset to configure.
*/
void setTemperatureOffset(float value);
/**
* Get the current humidity offset.
*
* @return The configured humidity offset.
*/
float getHumidityOffset();
/**
* Set the device humidity offset. The offset is applied by the
* device internally to the humidity reading. Valid values must
* be between -100 and 100.
*
* @param value The humidity offset to configure.
*/
void setHumidityOffset(float value);
/**
* Return the current relay set point (in PPM). This set point is
* the CO2 concentration point in PPM that causes the relay to
* trigger.
*
* @return The relay set point value.
*/
float getRelaySetPoint();
/**
* Set the relay set point in PPM. This set point is the CO2
* concentration point in PPM that causes the relay to trigger.
* Valid values are between 0-65535.
*
* @param value The desired relay set point value.
*/
void setRelaySetPoint(float value);
/**
* Return the current relay hysteresis.
*
* @return The relay hysteresis value.
*/
float getRelayHysteresis();
/**
* Set the relay hysteresis. Valid values are between 0-65535.
*
* @param value The desired relay set point value.
*/
void setRelayHysteresis(float value);
/**
* Return the current elevation setting (in meters).
*
* @return The current elevation setting.
*/
float getElevation();
/**
* Set the elevation setting in meters. Valid values are between
* 0-65535.
*
* @param value The desired elevation setting in meters.
*/
void setElevation(float value);
/**
* Return the current calibration single point value (in PPM).
*
* @return The current calibration single point value.
*/
float getCalibrationSinglePoint();
/**
* Set the calibration single point value in PPM. Valid values
* are between 0-65535.
*
* @param value The desired calibration single point value in PPM.
*/
void setCalibrationSinglePoint(float value);
/**
* Return the current baud rate.
*
* @return The current baud rate.
*/
float getBaudRate();
/**
* Return the current MAC address. The MAC address is configured
* via DIP switches within the device.
*
* @return The current MAC address.
*/
float getMACAddress();
/**
* Return the current ABC (Automatic Background Calibration)
* logic state. See the datasheet for details.
*
* @return The current ABC logic state.
*/
bool getABCLogicState();
/**
* Set the ABC (Automatic Background Calibration) logic state.
* Valid values are true for ON, false for OFF.
*
* @param value The desired ABC logic state.
*/
void setABCLogicState(bool value);
/**
* Return the current ABC (Automatic Background Calibration)
* reset state. See the datasheet for details.
*
* @return The current ABC reset state.
*/
bool getABCLogicReset();
/**
* Set the ABC (Automatic Background Calibration) reset state.
* Valid values are true for Reset, false for Normal.
*
* @param value The desired ABC reset state.
*/
void setABCLogicReset(bool value);
/**
* Return the current CO2 calibration state. See the datasheet
* for details.
*
* @return The current CO2 calibration state.
*/
bool getCO2Calibration();
/**
* Set the CO2 calibration state.
* Valid values are true for Calibrate, false for Normal.
*
* @param value The desired ABC reset state.
*/
void setCO2Calibration(bool value);
protected:
float m_humidity;
// always stored in C
float m_temperature;
float m_co2;
bool m_relayState;
private:
// Have we checked the device's temperature unit setting yet
bool m_isTempInitialized;
// Is the device configured for Celcius?
bool m_isCelcius;
};
}