diff --git a/lib/MiLight/MiLightRemoteConfig.cpp b/lib/MiLight/MiLightRemoteConfig.cpp index 7db763b3..067517e9 100644 --- a/lib/MiLight/MiLightRemoteConfig.cpp +++ b/lib/MiLight/MiLightRemoteConfig.cpp @@ -11,7 +11,8 @@ const MiLightRemoteConfig* MiLightRemoteConfig::ALL_REMOTES[] = { &FUT098Config, // rgb &FUT089Config, // 8-group rgb+cct (b8, fut089) &FUT091Config, - &FUT020Config + &FUT020Config, + &YellowPopConfig }; const size_t MiLightRemoteConfig::NUM_REMOTES = size(ALL_REMOTES); @@ -105,4 +106,12 @@ const MiLightRemoteConfig FUT020Config( REMOTE_TYPE_FUT020, "fut020", 0 -); \ No newline at end of file +); + +const MiLightRemoteConfig YellowPopConfig( + new YellowPopPacketFormatter(), + MiLightRadioConfig::ALL_CONFIGS[4], + REMOTE_TYPE_YELLOW_POP, + "yellow_pop", + 0 +); diff --git a/lib/MiLight/MiLightRemoteConfig.h b/lib/MiLight/MiLightRemoteConfig.h index 966bf16a..5c7e4886 100644 --- a/lib/MiLight/MiLightRemoteConfig.h +++ b/lib/MiLight/MiLightRemoteConfig.h @@ -8,6 +8,7 @@ #include #include #include +#include #include #ifndef _MILIGHT_REMOTE_CONFIG_H @@ -49,5 +50,6 @@ extern const MiLightRemoteConfig FUT089Config; //rgb+cct B8 / FUT089 extern const MiLightRemoteConfig FUT098Config; //rgb extern const MiLightRemoteConfig FUT091Config; //v2 cct extern const MiLightRemoteConfig FUT020Config; +extern const MiLightRemoteConfig YellowPopConfig; #endif diff --git a/lib/MiLight/YellowPopPacketFormatter.cpp b/lib/MiLight/YellowPopPacketFormatter.cpp new file mode 100644 index 00000000..f1e8524c --- /dev/null +++ b/lib/MiLight/YellowPopPacketFormatter.cpp @@ -0,0 +1,58 @@ +#include +#include + +// The remote slider lowpoint has a values of 0x90/144/-112, the midpoint 0x00, the highpoint 0x75/117 +uint8_t offset = 0x80; + +void YellowPopPacketFormatter::updateBrightness(uint8_t value) { + uint8_t remapped = Units::rescale(value, 255, 100.0); + int8_t brightness = (int8_t)remapped - offset; + command(static_cast(YellowPopCommand::BRIGHTNESS), brightness); +} + +void YellowPopPacketFormatter::updateStatus(MiLightStatus status, uint8_t groupId) { + if (status == MiLightStatus::OFF) { + command(static_cast(YellowPopCommand::OFF), 0); + } else if (status == MiLightStatus::ON) { + command(static_cast(YellowPopCommand::ON), 0); + } +} + +BulbId YellowPopPacketFormatter::parsePacket(const uint8_t* packet, JsonObject result) { + YellowPopCommand command = static_cast(packet[FUT02xPacketFormatter::FUT02X_COMMAND_INDEX] & 0x0F); + + BulbId bulbId( + (packet[1] << 8) | packet[2], + 0, + REMOTE_TYPE_YELLOW_POP + ); + + switch (command) { + case YellowPopCommand::ON: + result[F("state")] = F("ON"); + break; + + case YellowPopCommand::OFF: + result[F("state")] = F("OFF"); + break; + + case YellowPopCommand::BRIGHTNESS_LOW: + result[F("command")] = F("brightness_low"); + break; + + case YellowPopCommand::BRIGHTNESS_MID: + result[F("command")] = F("brightness_mid"); + break; + + case YellowPopCommand::BRIGHTNESS_HIGH: + result[F("command")] = F("brightness_high"); + break; + + case YellowPopCommand::BRIGHTNESS: + int8_t value = packet[FUT02xPacketFormatter::FUT02X_ARGUMENT_INDEX]; + result[GroupStateFieldNames::BRIGHTNESS] = value + offset; + break; + } + + return bulbId; +} diff --git a/lib/MiLight/YellowPopPacketFormatter.h b/lib/MiLight/YellowPopPacketFormatter.h new file mode 100644 index 00000000..6e2b1389 --- /dev/null +++ b/lib/MiLight/YellowPopPacketFormatter.h @@ -0,0 +1,24 @@ +#include + +#pragma once + +enum class YellowPopCommand { + ON = 0x02, + OFF = 0x05, + BRIGHTNESS_LOW = 0x01, + BRIGHTNESS_MID = 0x04, + BRIGHTNESS_HIGH = 0x03, + BRIGHTNESS = 0x00 +}; + +class YellowPopPacketFormatter : public FUT02xPacketFormatter { +public: + YellowPopPacketFormatter() + : FUT02xPacketFormatter(REMOTE_TYPE_YELLOW_POP) + { } + + virtual void updateStatus(MiLightStatus status, uint8_t groupId); + virtual void updateBrightness(uint8_t value); + + virtual BulbId parsePacket(const uint8_t* packet, JsonObject result) override; +}; diff --git a/lib/Types/MiLightRemoteType.cpp b/lib/Types/MiLightRemoteType.cpp index ecd787c4..50d9cd56 100644 --- a/lib/Types/MiLightRemoteType.cpp +++ b/lib/Types/MiLightRemoteType.cpp @@ -8,6 +8,7 @@ static const char* REMOTE_NAME_FUT089 = "fut089"; static const char* REMOTE_NAME_RGB = "rgb"; static const char* REMOTE_NAME_FUT091 = "fut091"; static const char* REMOTE_NAME_FUT020 = "fut020"; +static const char* REMOTE_NAME_YELLOW_POP = "yellow_pop"; const MiLightRemoteType MiLightRemoteTypeHelpers::remoteTypeFromString(const String& type) { if (type.equalsIgnoreCase(REMOTE_NAME_RGBW) || type.equalsIgnoreCase("fut096")) { @@ -38,6 +39,10 @@ const MiLightRemoteType MiLightRemoteTypeHelpers::remoteTypeFromString(const Str return REMOTE_TYPE_FUT020; } + if (type.equalsIgnoreCase(REMOTE_NAME_YELLOW_POP)) { + return REMOTE_TYPE_YELLOW_POP; + } + Serial.print(F("remoteTypeFromString: ERROR - tried to fetch remote config for type: ")); Serial.println(type); @@ -60,6 +65,8 @@ const String MiLightRemoteTypeHelpers::remoteTypeToString(const MiLightRemoteTyp return REMOTE_NAME_FUT091; case REMOTE_TYPE_FUT020: return REMOTE_NAME_FUT020; + case REMOTE_TYPE_YELLOW_POP: + return REMOTE_NAME_YELLOW_POP; default: Serial.print(F("remoteTypeToString: ERROR - tried to fetch remote config name for unknown type: ")); Serial.println(type); @@ -100,4 +107,4 @@ const bool MiLightRemoteTypeHelpers::supportsColorTemp(const MiLightRemoteType t default: return false; } -} \ No newline at end of file +} diff --git a/lib/Types/MiLightRemoteType.h b/lib/Types/MiLightRemoteType.h index e8a648a7..549ea83b 100644 --- a/lib/Types/MiLightRemoteType.h +++ b/lib/Types/MiLightRemoteType.h @@ -10,7 +10,8 @@ enum MiLightRemoteType { REMOTE_TYPE_RGB = 3, REMOTE_TYPE_FUT089 = 4, REMOTE_TYPE_FUT091 = 5, - REMOTE_TYPE_FUT020 = 6 + REMOTE_TYPE_FUT020 = 6, + REMOTE_TYPE_YELLOW_POP = 7 }; class MiLightRemoteTypeHelpers { @@ -20,4 +21,4 @@ class MiLightRemoteTypeHelpers { static const bool supportsRgb(const MiLightRemoteType type); static const bool supportsRgbw(const MiLightRemoteType type); static const bool supportsColorTemp(const MiLightRemoteType type); -}; \ No newline at end of file +}; diff --git a/web2/api/api-zod.ts b/web2/api/api-zod.ts index 5530b96b..b630c82a 100644 --- a/web2/api/api-zod.ts +++ b/web2/api/api-zod.ts @@ -9,6 +9,7 @@ const RemoteType = z.enum([ "fut089", "fut091", "fut020", + "yellow_pop", ]); const Alias = z .object({ @@ -805,7 +806,7 @@ const endpoints = makeApi([ name: "remoteType", type: "Path", schema: z - .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020"]) + .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020", "yellow_pop"]) .describe( "Type of remote to read a packet from. If unspecified, will read packets from all remote types." ), @@ -933,7 +934,7 @@ const endpoints = makeApi([ name: "remoteType", type: "Path", schema: z - .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020"]) + .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020", "yellow_pop"]) .describe( "Type of remote to read a packet from. If unspecified, will read packets from all remote types." ), @@ -986,7 +987,7 @@ if `fmt` is set to `normalized`, the response will be in nor name: "remoteType", type: "Path", schema: z - .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020"]) + .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020", "yellow_pop"]) .describe( "Type of remote to read a packet from. If unspecified, will read packets from all remote types." ), @@ -1049,7 +1050,7 @@ if `fmt` is set to `normalized`, the response will be in nor name: "remoteType", type: "Path", schema: z - .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020"]) + .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020", "yellow_pop"]) .describe( "Type of remote to read a packet from. If unspecified, will read packets from all remote types." ), @@ -1084,7 +1085,7 @@ if `fmt` is set to `normalized`, the response will be in nor name: "remoteType", type: "Path", schema: z - .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020"]) + .enum(["rgbw", "cct", "rgb_cct", "rgb", "fut089", "fut091", "fut020", "yellow_pop"]) .describe( "Type of remote to read a packet from. If unspecified, will read packets from all remote types." ), diff --git a/web2/components/light/remote-data.ts b/web2/components/light/remote-data.ts index 660dae07..e0ee17cd 100644 --- a/web2/components/light/remote-data.ts +++ b/web2/components/light/remote-data.ts @@ -16,7 +16,8 @@ export const RemoteTypeDescriptions: Record = { rgb: "Compatible with most RGB LED Strip Controllers.", fut089: "Compatible with most newer RGB + dual white bulbs and controllers.", fut091: "Compatible with most newer dual white bulbs and controllers.", - fut020: "Compatible with some RGB LED strip controllers." + fut020: "Compatible with some RGB LED strip controllers.", + yellow_pop: "Compatible with Yellow Pop LED neon signs." }; export const RemoteTypeCapabilities: Record = { @@ -54,5 +55,10 @@ export const RemoteTypeCapabilities: Record = { brightness: true, color: true, colorTemp: false + }, + yellow_pop: { + brightness: true, + color: false, + colorTemp: false } };