mirror of
https://github.com/nymea/nymea-plugins.git
synced 2026-08-05 03:33:51 +02:00
331 lines
8.2 KiB
C++
331 lines
8.2 KiB
C++
#include "nymealight.h"
|
|
|
|
NymeaLight::NymeaLight(WS2812FX *strip) :
|
|
m_strip(strip)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
NymeaLight::NymeaLight(SoftwareSerial *serial, WS2812FX *strip) :
|
|
m_softwareSerial(serial),
|
|
m_strip(strip)
|
|
{
|
|
|
|
}
|
|
|
|
NymeaLight::NymeaLight(HardwareSerial &serial, WS2812FX *strip) :
|
|
m_hardwareSerial(&serial),
|
|
m_strip(strip)
|
|
{
|
|
|
|
}
|
|
|
|
WS2812FX *NymeaLight::strip() const
|
|
{
|
|
return m_strip;
|
|
}
|
|
|
|
void NymeaLight::init()
|
|
{
|
|
// Get rid of unused warning from lib
|
|
(void)&_modes;
|
|
|
|
// Initialize serial port
|
|
if (m_hardwareSerial) {
|
|
m_hardwareSerial->begin(115200);
|
|
} else if (m_softwareSerial) {
|
|
m_softwareSerial->begin(115200);
|
|
}
|
|
|
|
// Initialize strip
|
|
m_strip->init();
|
|
if (m_power) {
|
|
m_strip->setBrightness(m_brightness);
|
|
} else {
|
|
m_strip->setBrightness(0);
|
|
}
|
|
m_strip->setSpeed(m_speed);
|
|
m_strip->setColor(0xff, 0xff, 0xff);
|
|
m_strip->setMode(FX_MODE_STATIC);
|
|
m_strip->start();
|
|
|
|
m_previouseTime = millis();
|
|
sendReadyNotification();
|
|
}
|
|
|
|
void NymeaLight::process()
|
|
{
|
|
// Read incoming data if there is any
|
|
readData();
|
|
|
|
//doAnimations();
|
|
|
|
// Perform service for WS2812FX
|
|
m_strip->service();
|
|
}
|
|
|
|
void NymeaLight::doAnimations()
|
|
{
|
|
// Perform animation steps every 50 ms
|
|
uint32_t currentTimestamp = millis();
|
|
if (m_previouseTime - currentTimestamp > 50000) {
|
|
//debugPrint("Tick");
|
|
m_previouseTime = currentTimestamp;
|
|
|
|
if (m_brightnessFadeDuration > 0 && m_brightnessTargetValue != m_strip->getBrightness()) {
|
|
// Calculate step for brightness animation
|
|
if (m_brightnessStartValue < m_brightnessTargetValue) {
|
|
m_strip->setBrightness(m_strip->getBrightness() - 1);
|
|
} else {
|
|
m_strip->setBrightness(m_strip->getBrightness() + 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void NymeaLight::debugPrint(const char message[])
|
|
{
|
|
streamByte(SlipProtocolEnd, true);
|
|
streamByte(NotificationDebugMessage);
|
|
streamByte(m_notificationId);
|
|
m_notificationId++;
|
|
for (size_t i = 0; i < strlen(message); i++) {
|
|
streamByte(message[i]);
|
|
}
|
|
streamByte(SlipProtocolEnd, true);
|
|
flushSerial();
|
|
}
|
|
|
|
void NymeaLight::flushSerial()
|
|
{
|
|
if (m_hardwareSerial) {
|
|
m_hardwareSerial->flush();
|
|
} else if (m_softwareSerial) {
|
|
m_softwareSerial->flush();
|
|
}
|
|
}
|
|
|
|
void NymeaLight::sendReadyNotification()
|
|
{
|
|
streamByte(SlipProtocolEnd, true);
|
|
streamByte(NotificationReady);
|
|
streamByte(m_notificationId);
|
|
m_notificationId++;
|
|
streamByte(SlipProtocolEnd, true);
|
|
flushSerial();
|
|
}
|
|
|
|
void NymeaLight::readData()
|
|
{
|
|
if (m_hardwareSerial) {
|
|
while (m_hardwareSerial->available()) {
|
|
uint8_t receivedByte = m_hardwareSerial->read();
|
|
processReceivedByte(receivedByte);
|
|
}
|
|
} else if (m_softwareSerial) {
|
|
while (m_softwareSerial->available()) {
|
|
uint8_t receivedByte = m_softwareSerial->read();
|
|
processReceivedByte(receivedByte);
|
|
}
|
|
}
|
|
}
|
|
|
|
void NymeaLight::processData(uint8_t buffer[], uint8_t length)
|
|
{
|
|
uint8_t command = buffer[0];
|
|
uint8_t requestId = buffer[1];
|
|
|
|
switch (command) {
|
|
case CommandGetStatus: {
|
|
if (length != 2) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandSetPower: {
|
|
if (length != 5) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
// uint16_t fadeDuration = (buffer[2] << 8 ) | buffer[3];
|
|
uint8_t powerInt = buffer[4];
|
|
if (powerInt == 0) {
|
|
m_power = false;
|
|
} else {
|
|
m_power = true;
|
|
}
|
|
|
|
if (m_power) {
|
|
m_strip->setBrightness(m_brightness);
|
|
} else {
|
|
m_strip->setBrightness(0);
|
|
}
|
|
|
|
// TODO: animate brightness with fade duration
|
|
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandSetColor: {
|
|
if (length != 7) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
//uint32_t currentColor = m_strip->getColor();
|
|
//uint32_t targetColor = ((uint32_t) << 16) | ((uint32_t)buffer[5] << 8) | buffer[6];
|
|
// uint16_t fadeDuration = (buffer[2] << 8 ) | buffer[3];
|
|
uint8_t red = buffer[4];
|
|
uint8_t green = buffer[5];
|
|
uint8_t blue = buffer[6];
|
|
m_strip->setColor(red, green, blue);
|
|
delayMicroseconds(1000);
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandSetBrightness: {
|
|
if (length != 5) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
//uint16_t fadeDuration = (buffer[2] << 8 ) | buffer[3];
|
|
// m_brightnessStartValue = m_strip->getBrightness();
|
|
|
|
m_brightness = buffer[4];
|
|
if (m_power) {
|
|
m_strip->setBrightness(m_brightness);
|
|
}
|
|
|
|
delayMicroseconds(1000);
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandSetSpeed: {
|
|
if (length != 6) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
// uint16_t fadeDuration = (buffer[2] << 8 ) | buffer[3];
|
|
uint16_t speed = (buffer[4] << 8 ) | buffer[5];
|
|
m_strip->setSpeed(speed);
|
|
delayMicroseconds(1000);
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandSetEffect: {
|
|
if (length != 3) {
|
|
sendResponse(command, requestId, StatusInvalidPlayload);
|
|
return;
|
|
}
|
|
|
|
m_strip->setMode(buffer[2]);
|
|
delayMicroseconds(1000);
|
|
sendResponse(command, requestId, StatusSuccess);
|
|
break;
|
|
}
|
|
|
|
case CommandCustom:
|
|
|
|
break;
|
|
|
|
default:
|
|
sendResponse(command, requestId, StatusInvalidCommand);
|
|
break;
|
|
}
|
|
|
|
m_strip->show();
|
|
m_strip->service();
|
|
}
|
|
|
|
void NymeaLight::sendResponse(uint8_t command, uint8_t requestId, Status status)
|
|
{
|
|
streamByte(SlipProtocolEnd, true);
|
|
streamByte(command);
|
|
streamByte(requestId);
|
|
streamByte(status);
|
|
streamByte(SlipProtocolEnd, true);
|
|
|
|
flushSerial();
|
|
}
|
|
|
|
void NymeaLight::processReceivedByte(uint8_t receivedByte)
|
|
{
|
|
if (m_protocolEscaping) {
|
|
switch (receivedByte) {
|
|
case SlipProtocolTransposedEnd:
|
|
m_buffer[m_bufferIndex++] = SlipProtocolEnd;
|
|
m_protocolEscaping = false;
|
|
break;
|
|
case SlipProtocolTransposedEsc:
|
|
m_buffer[m_bufferIndex++] = SlipProtocolEsc;
|
|
m_protocolEscaping = false;
|
|
break;
|
|
default:
|
|
// SLIP protocol violation...received escape, but it is not an escaped byte
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (receivedByte) {
|
|
case SlipProtocolEnd:
|
|
// We are done with this package, process it and reset the buffer
|
|
if (m_bufferIndex > 0) {
|
|
processData(m_buffer, m_bufferIndex);
|
|
}
|
|
m_bufferIndex = 0;
|
|
m_protocolEscaping = false;
|
|
break;
|
|
case SlipProtocolEsc:
|
|
// The next byte will be escaped, lets wait for it
|
|
m_protocolEscaping = true;
|
|
break;
|
|
default:
|
|
// Nothing special, just add to buffer
|
|
m_buffer[m_bufferIndex++] = receivedByte;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void NymeaLight::streamByte(uint8_t dataByte, boolean specialCharacter)
|
|
{
|
|
// If this is a special character, write it without escaping
|
|
if (specialCharacter) {
|
|
writeByte(dataByte);
|
|
} else {
|
|
switch (dataByte) {
|
|
case SlipProtocolEnd:
|
|
writeByte(SlipProtocolEsc);
|
|
writeByte(SlipProtocolTransposedEnd);
|
|
break;
|
|
case SlipProtocolEsc:
|
|
writeByte(SlipProtocolEsc);
|
|
writeByte(SlipProtocolTransposedEsc);
|
|
break;
|
|
default:
|
|
writeByte(dataByte);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NymeaLight::writeByte(uint8_t dataByte)
|
|
{
|
|
if (m_hardwareSerial) {
|
|
m_hardwareSerial->write(dataByte);
|
|
} else if (m_softwareSerial) {
|
|
m_softwareSerial->write(dataByte);
|
|
}
|
|
}
|