-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for sensors #7
Changes from all commits
8f989f5
a4880bb
175db2a
6a15c43
9d63952
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,6 +44,7 @@ | |
// 12.04.2015 change of using datatype boolean to bool8. | ||
// 15.06.2015 On DMX lines sometimes a BREAK condition occures inbetween RDM packets from the controller | ||
// and the device response. Ignore that when no data has arrived. | ||
// 25.05.2017 Stefan Krupop: Add support for sensors | ||
// - - - - - | ||
|
||
#include "Arduino.h" | ||
|
@@ -344,14 +345,15 @@ int random255(); | |
|
||
// Initialize or reinitialize the DMX RDM mode. | ||
// The other values are stored for later use with the specific commands. | ||
void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, uint8_t modePin, uint8_t modeIn, uint8_t modeOut) | ||
void DMXSerialClass2::init(struct RDMINIT *initData, RDMCallbackFunction func, RDMGetSensorValue sensorFunc, uint8_t modePin, uint8_t modeIn, uint8_t modeOut) | ||
{ | ||
// This structure is defined for mapping the values in the EEPROM | ||
struct EEPROMVALUES eeprom; | ||
|
||
// save the given initData for later use. | ||
_initData = initData; | ||
_rdmFunc = func; | ||
_sensorFunc = sensorFunc; | ||
|
||
_dmxModePin = modePin; | ||
_dmxModeIn = modeIn; | ||
|
@@ -452,6 +454,11 @@ void DMXSerialClass2::attachRDMCallback(RDMCallbackFunction newFunction) | |
_rdmFunc = newFunction; | ||
} // attachRDMCallback | ||
|
||
// Register a self implemented function to get sensor values | ||
void DMXSerialClass2::attachSensorCallback(RDMGetSensorValue newFunction) | ||
{ | ||
_sensorFunc = newFunction; | ||
} // attachSensorCallback | ||
|
||
// some functions to hide the internal variables from beeing changed | ||
|
||
|
@@ -663,7 +670,7 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool | |
devInfo->personalityCount = 1; | ||
devInfo->startAddress = SWAPINT(_startAddress); | ||
devInfo->subDeviceCount = 0; | ||
devInfo->sensorCount = 0; | ||
devInfo->sensorCount = _initData->sensorsLength; | ||
|
||
_rdm.packet.DataLength = sizeof(DEVICEINFO); | ||
handled = true; | ||
|
@@ -793,8 +800,15 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool | |
WRITEINT(_rdm.packet.Data , E120_MANUFACTURER_LABEL); | ||
WRITEINT(_rdm.packet.Data+ 2, E120_DEVICE_MODEL_DESCRIPTION); | ||
WRITEINT(_rdm.packet.Data+ 4, E120_DEVICE_LABEL); | ||
uint8_t offset = 6; | ||
if (_initData->sensorsLength > 0) { | ||
_rdm.packet.DataLength += 2 * 2; | ||
offset += 2 * 2; | ||
WRITEINT(_rdm.packet.Data+ 6, E120_SENSOR_DEFINITION); | ||
WRITEINT(_rdm.packet.Data+ 8, E120_SENSOR_VALUE); | ||
} | ||
for (int n = 0; n < _initData->additionalCommandsLength; n++) { | ||
WRITEINT(_rdm.packet.Data+6+n+n, _initData->additionalCommands[n]); | ||
WRITEINT(_rdm.packet.Data+offset+n+n, _initData->additionalCommands[n]); | ||
} | ||
handled = true; | ||
} | ||
|
@@ -805,6 +819,79 @@ void DMXSerialClass2::_processRDMMessage(byte CmdClass, uint16_t Parameter, bool | |
|
||
// ADD: PARAMETER_DESCRIPTION | ||
|
||
} else if (Parameter == SWAPINT(E120_SENSOR_DEFINITION) && _initData->sensorsLength > 0) { // 0x0200 | ||
if (CmdClass == E120_GET_COMMAND) { | ||
if (_rdm.packet.DataLength != 1) { | ||
// Unexpected data | ||
nackReason = E120_NR_FORMAT_ERROR; | ||
} else if (_rdm.packet.SubDev != 0) { | ||
// No sub-devices supported | ||
nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; | ||
} else { | ||
uint8_t sensorNr = _rdm.packet.Data[0]; | ||
if (sensorNr >= _initData->sensorsLength) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should also check that sensorNr < 0xff (all sensors) either here, or at init time. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm... sensorsLength is defined as uint8_t, so the highest possible value would be 0xff anyway. As the "if" here checks for larger or equal, it would return E120_NR_DATA_OUT_OF_RANGE when the user would have defined 255 sensors and sensorNr is 0xff. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's sort of my point, you can only have 254 sensors, but you could technically pass 255 into the system. It probably really wants to be at init time, but you ought to ignore a sensor 255, as that's reserved for "all sensors". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Isn't this exactly what is happening? If the user should have passed 255 sensors, sensorsLength would also be 255. If then sensor 255 is requested, the library replies with E120_NR_DATA_OUT_OF_RANGE instead of the sensor data, effectively ignoring it. Sorry, but I still do not see the case where this is problematic... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep fair point. I think it needs trapping/overwriting earlier though as otherwise devInfo->sensorCount will be populated by it, which can't be valid. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, double-checking the standard, it says "Valid sensor numbers are in the range from 0x00 – 0xFE. The sensor number 0xFF is used to address all sensors." and "When a device or sub-device is fitted with a single sensor, it would return a value of 0x01 for the Sensor Count. This sensor would then be addressed as Sensor Number 0x00 when using the other sensor-related parameter messages.". So you can have 255 sensors, which are addressed as 0 to 254. |
||
// Out of range sensor | ||
nackReason = E120_NR_DATA_OUT_OF_RANGE; | ||
} else { | ||
_rdm.packet.DataLength = 13 + strlen(_initData->sensors[sensorNr].description); | ||
_rdm.packet.Data[0] = sensorNr; | ||
_rdm.packet.Data[1] = _initData->sensors[sensorNr].type; | ||
_rdm.packet.Data[2] = _initData->sensors[sensorNr].unit; | ||
_rdm.packet.Data[3] = _initData->sensors[sensorNr].prefix; | ||
WRITEINT(_rdm.packet.Data + 4, _initData->sensors[sensorNr].rangeMin); | ||
WRITEINT(_rdm.packet.Data + 6, _initData->sensors[sensorNr].rangeMax); | ||
WRITEINT(_rdm.packet.Data + 8, _initData->sensors[sensorNr].normalMin); | ||
WRITEINT(_rdm.packet.Data + 10, _initData->sensors[sensorNr].normalMax); | ||
_rdm.packet.Data[12] = (_initData->sensors[sensorNr].lowHighSupported ? 2 : 0) | (_initData->sensors[sensorNr].recordedSupported ? 1 : 0); | ||
memcpy(_rdm.packet.Data + 13, _initData->sensors[sensorNr].description, _rdm.packet.DataLength - 13); | ||
handled = true; | ||
} | ||
} | ||
} else if (CmdClass == E120_SET_COMMAND) { | ||
// Unexpected set | ||
nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; | ||
} | ||
} else if (Parameter == SWAPINT(E120_SENSOR_VALUE) && _initData->sensorsLength > 0) { // 0x0201 | ||
if (CmdClass == E120_GET_COMMAND) { | ||
if (_rdm.packet.DataLength != 1) { | ||
// Unexpected data | ||
nackReason = E120_NR_FORMAT_ERROR; | ||
} else if (_rdm.packet.SubDev != 0) { | ||
// No sub-devices supported | ||
nackReason = E120_NR_SUB_DEVICE_OUT_OF_RANGE; | ||
} else { | ||
uint8_t sensorNr = _rdm.packet.Data[0]; | ||
if (sensorNr >= _initData->sensorsLength) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again 0xff. |
||
// Out of range sensor | ||
nackReason = E120_NR_DATA_OUT_OF_RANGE; | ||
} else { | ||
int16_t sensorValue = 0; | ||
int16_t lowestValue = 0; | ||
int16_t highestValue = 0; | ||
int16_t recordedValue = 0; | ||
bool8 res = false; | ||
if (_sensorFunc) { | ||
res = _sensorFunc(sensorNr, &sensorValue, &lowestValue, &highestValue, &recordedValue); | ||
} | ||
if (res) { | ||
_rdm.packet.DataLength = 9; | ||
_rdm.packet.Data[0] = sensorNr; | ||
WRITEINT(_rdm.packet.Data + 1, sensorValue); | ||
WRITEINT(_rdm.packet.Data + 3, lowestValue); | ||
WRITEINT(_rdm.packet.Data + 5, highestValue); | ||
WRITEINT(_rdm.packet.Data + 7, recordedValue); | ||
handled = true; | ||
} else { | ||
nackReason = E120_NR_HARDWARE_FAULT; | ||
} | ||
} | ||
} | ||
} else if (CmdClass == E120_SET_COMMAND) { | ||
// Unhandled set. Set on a sensor is used to reset stats. | ||
// User should process it in own handler when sensor supports high/low or recorded value. | ||
nackReason = E120_NR_UNSUPPORTED_COMMAND_CLASS; | ||
} | ||
|
||
} else { | ||
handled = false; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will break people's existing code, you should probably either stick it at the end, or do a wrapper version of the old prototype which calls the new one with a NULL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, added init with "old" signature in header