Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions include/ShockerModelType.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
#pragma once

#include "serialization/_fbs/ShockerModelType_generated.h"

#include <cstdint>
#include <cstring>

namespace OpenShock {
typedef OpenShock::Serialization::Types::ShockerModelType ShockerModelType;
enum class ShockerModelType : uint8_t {
CaiXianlin,
Petrainer,
Petrainer998DR,
T330,
D80
};

inline bool ShockerModelTypeFromString(const char* str, ShockerModelType& out, bool allowTypo = false) {
if (strcasecmp(str, "caixianlin") == 0 || strcasecmp(str, "cai-xianlin") == 0) {
Expand Down Expand Up @@ -34,6 +38,16 @@ namespace OpenShock {
return true;
}

if (strcasecmp(str, "t330") == 0) {
out = ShockerModelType::T330;
return true;
}

if (strcasecmp(str, "d80") == 0) {
out = ShockerModelType::D80;
return true;
}

return false;
}
} // namespace OpenShock
12 changes: 12 additions & 0 deletions include/radio/rmt/D80Encoder.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#include "ShockerCommandType.h"

#include <esp32-hal-rmt.h>

#include <cstdint>

namespace OpenShock::Rmt::D80Encoder {
size_t GetBufferSize();
bool FillBuffer(rmt_data_t* data, uint16_t shockerId, ShockerCommandType type, uint8_t intensity);
}
24 changes: 23 additions & 1 deletion src/message_handlers/websocket/gateway/ShockerCommandList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ void _Private::HandleShockerCommandList(const OpenShock::Serialization::Gateway:
FbsModelType fbsModel = command->model();
FbsCommandType fbsCommandType = command->type();

OpenShock::ShockerModelType model;
switch (fbsModel) {
case FbsModelType::CaiXianlin:
model = OpenShock::ShockerModelType::CaiXianlin;
break;
case FbsModelType::Petrainer:
model = OpenShock::ShockerModelType::Petrainer;
break;
case FbsModelType::Petrainer998DR:
model = OpenShock::ShockerModelType::Petrainer998DR;
break;
// case FbsModelType::T330:
// model = OpenShock::ShockerModelType::T330;
// break;
// case FbsModelType::D80:
// model = OpenShock::ShockerModelType::D80;
// break;
default:
OS_LOGE(TAG, "Unsupported shocker model: %s", OpenShock::Serialization::Types::EnumNameShockerModelType(fbsModel));
continue;
}

OpenShock::ShockerCommandType commandType;
switch (fbsCommandType) {
case FbsCommandType::Stop:
Expand All @@ -57,7 +79,7 @@ void _Private::HandleShockerCommandList(const OpenShock::Serialization::Gateway:
continue;
}

if (!OpenShock::CommandHandler::HandleCommand(fbsModel, id, commandType, intensity, durationMs)) {
if (!OpenShock::CommandHandler::HandleCommand(model, id, commandType, intensity, durationMs)) {
OS_LOGE(TAG, "Remote command failed/rejected!");
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/radio/RFTransmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const char* const TAG = "RFTransmitter";

#include <freertos/queue.h>

#include <vector>

const UBaseType_t kQueueSize = 64;
const BaseType_t kTaskPriority = 1;
const uint32_t kTaskStackSize = 4096; // PROFILED: 1.4KB stack usage
Expand Down
3 changes: 3 additions & 0 deletions src/radio/rmt/CaiXianlinEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ bool Rmt::CaiXianlinEncoder::FillBuffer(rmt_data_t* sequence, uint16_t shockerId
typeVal = 0x03;
intensity = 0; // Sound intensity must be 0 for some shockers, otherwise it wont work, or they soft lock until restarted
break;
case ShockerCommandType::Light:
typeVal = 0x04;
break;
default:
return false; // Invalid type
}
Expand Down
62 changes: 62 additions & 0 deletions src/radio/rmt/D80Encoder.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "radio/rmt/D80Encoder.h"

#include "radio/rmt/internal/Shared.h"

#include "Checksum.h"

#include <algorithm>

const rmt_data_t kRmtPreamble = {1900, 1, 4000, 0};
const rmt_data_t kRmtOne = {900, 1, 300, 0};
const rmt_data_t kRmtZero = {300, 1, 900, 0};
const rmt_data_t kRmtPostamble = {200, 1, 2200, 0};

using namespace OpenShock;

size_t Rmt::D80Encoder::GetBufferSize()
{
return 42;
}

bool Rmt::D80Encoder::FillBuffer(rmt_data_t* sequence, uint16_t shockerId, ShockerCommandType type, uint8_t intensity)
{
// Intensity must be between 0 and 15, this should mimic the rounding of the original remote which
// allows you to select from 1-99 when the protocol only has 4 bits for intensity (0-15).
if (intensity > 0)
intensity = std::max((intensity*15)/100, 1);

uint8_t typeVal = 0;
switch (type) {
case ShockerCommandType::Shock:
typeVal = 0x01;
break;
case ShockerCommandType::Vibrate:
typeVal = 0x02;
break;
case ShockerCommandType::Sound:
typeVal = 0x03;
intensity = 0; // The remote always sends 0, I don't know what happens if you send something else.
break;
default:
return false; // Invalid type
}

uint8_t channelId = 1; // Channel ID is 1 or 2 for separate control or 3 for both channels

// Payload layout: 00000100[shockerId:16][type:2][channelId:2][intensity:4]
// The first byte is always 0x04, the two remotes both use this and it wont pair to other values.
uint32_t payload = 0x04000000 | (static_cast<uint32_t>(shockerId) << 8) | (static_cast<uint32_t>(typeVal & 0x3) << 6) | (static_cast<uint32_t>(channelId & 0x3) << 4) | static_cast<uint32_t>(intensity & 0xF);

// Calculate the checksum of the payload
uint8_t checksum = Checksum::Sum8(payload);

// Add the checksum to the payload
uint64_t data = (static_cast<uint64_t>(payload) << 8) | static_cast<uint64_t>(checksum);

// Generate the sequence
sequence[0] = kRmtPreamble;
Rmt::Internal::EncodeBits<40>(sequence + 1, data, kRmtOne, kRmtZero);
sequence[41] = kRmtPostamble;

return true;
}
9 changes: 9 additions & 0 deletions src/radio/rmt/Sequence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const char* const TAG = "Sequence";
#include "radio/rmt/Petrainer998DREncoder.h"
#include "radio/rmt/PetrainerEncoder.h"
#include "radio/rmt/T330Encoder.h"
#include "radio/rmt/D80Encoder.h"

using namespace OpenShock;

Expand All @@ -19,6 +20,10 @@ inline static size_t getSequenceBufferSize(ShockerModelType shockerModelType)
return Rmt::Petrainer998DREncoder::GetBufferSize();
case ShockerModelType::Petrainer:
return Rmt::PetrainerEncoder::GetBufferSize();
case ShockerModelType::T330:
return Rmt::T330Encoder::GetBufferSize();
case ShockerModelType::D80:
return Rmt::D80Encoder::GetBufferSize();
default:
return 0;
}
Expand All @@ -33,6 +38,10 @@ inline static bool fillSequenceImpl(rmt_data_t* data, ShockerModelType modelType
return Rmt::PetrainerEncoder::FillBuffer(data, shockerId, commandType, intensity);
case ShockerModelType::Petrainer998DR:
return Rmt::Petrainer998DREncoder::FillBuffer(data, shockerId, commandType, intensity);
case ShockerModelType::T330:
return Rmt::T330Encoder::FillBuffer(data, shockerId, commandType, intensity);
case ShockerModelType::D80:
return Rmt::D80Encoder::FillBuffer(data, shockerId, commandType, intensity);
default:
OS_LOGE(TAG, "Unknown shocker model: %u", modelType);
return false;
Expand Down
2 changes: 1 addition & 1 deletion src/serial/command_handlers/rftransmit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ OpenShock::Serial::CommandGroup OpenShock::Serial::CommandHandlers::RfTransmitHa
"json"sv,
"must be a JSON object with the following fields:"sv,
"{\"model\":\"caixianlin\",\"id\":12345,\"type\":\"vibrate\",\"intensity\":99,\"durationMs\":500}"sv,
{"model (string) Model of the shocker (\"caixianlin\", \"petrainer\", \"petrainer998dr\")"sv,
{"model (string) Model of the shocker (\"caixianlin\", \"petrainer\", \"petrainer998dr\", \"t330\", \"d80\")"sv,
"id (number) ID of the shocker (0-65535)"sv,
"type (string) Type of the command (\"shock\", \"vibrate\", \"sound\", \"light\", \"stop\")"sv,
"intensity (number) Intensity of the command (0-255)"sv,
Expand Down
4 changes: 2 additions & 2 deletions src/serialization/JsonSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ bool JsonSerial::ParseShockerCommand(const cJSON* root, JsonSerial::ShockerComma
OS_LOGE(TAG, "value at 'model' is not a string");
return false;
}
ShockerModelType modelType = ShockerModelType::MIN;
ShockerModelType modelType = ShockerModelType::CaiXianlin;
if (!ShockerModelTypeFromString(model->valuestring, modelType)) {
OS_LOGE(TAG, "value at 'model' is not a valid shocker model (caixianlin, petrainer, petrainer998dr)");
OS_LOGE(TAG, "value at 'model' is not a valid shocker model (caixianlin, petrainer, petrainer998dr, t330, d80)");
return false;
}

Expand Down
Loading