Does someone have ESP82266 Lifx toggle power switch working code?

I am trying to build a one button ESP8266 switch to control one of my Lifx bulbs.
I am not a coder so I’ve searched to find a working code designed by someone but none of the ones I found did work. So would love to hear from this community if one has build one and if possible share the code to tyr.

Yeah, just a sec. This is a cut-down version of my current controller. Should toggle a light on and off on button press. If you want a two-way switch (like a normal light switch) then I can remove all the debounce stuff and check buttonState and set “HIGH” to on, and “LOW” to off.

It’s based on code I originally got off this forum and iterated on. The tricky stuff is setting up the packet structure. Once you’ve done that you can wrap it all up in a function (SetPower) and call it

NB: there’s a bit of code around checking for a “held” button, but you can probably ignore that.

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>

// ---- Network Settings ----

//wifi setup
const char* ssid = "your network";
const char* password = "your password";

// Remote IP (In this case we broadcast to the entire subnet - .1 for me, might be different for you)
IPAddress broadcast_ip(192, 168, 1, 255);

//the light's mac address - update
uint8_t dest[] = {0xd0, 0x73, 0xd5, 0xab, 0xcd, 0xef};

// the ESP pin you're using
#define buttonPin 4

// Port we listen to
unsigned int localPort = 8888;

// Port for talking to LIFX devices
unsigned int lifxPort  = 56700;

// --- LIFX Protocol ---
// The LIFX Header structure
#pragma pack(push, 1)
typedef struct {
  /* frame */
  uint16_t size;
  uint16_t protocol: 12;
  uint8_t  addressable: 1;
  uint8_t  tagged: 1;
  uint8_t  origin: 2;
  uint32_t source;
  /* frame address */
  uint8_t  target[8];
  uint8_t  reserved[6];
  uint8_t  res_required: 1;
  uint8_t  ack_required: 1;
  uint8_t  : 6;
  uint8_t  sequence;
  /* protocol header */
  uint64_t : 64;
  uint16_t type;
  uint16_t : 16;
  /* variable length payload follows */
} lifx_header;
#pragma pack(pop)

#pragma pack(push, 1)
typedef struct {
  uint16_t color[4];
  int16_t  reserved;
  uint16_t power;
  char label[32];
  uint64_t reserved2;
} lifx_light_state;
#pragma pack(pop)

// Device::SetPower Payload
#pragma pack(push, 1)
typedef struct {
  uint16_t level;
} lifx_payload_device_set_power;
#pragma pack(pop)

// Device::StatePower Payload
#pragma pack(push, 1)
typedef struct {
  uint16_t level;
} lifx_payload_device_state_power;
#pragma pack(pop)

#pragma pack(push, 1)
typedef struct {
    uint8_t     reserved;
    uint16_t    color[4];
    uint32_t    duration;
} lifx_payload_light_set_color;
#pragma pack(pop)

// Payload types
#define LIFX_DEVICE_GETPOWER 20
#define LIFX_DEVICE_SETPOWER 21
#define LIFX_DEVICE_STATEPOWER 22
#define LIFX_LIGHT_GETSTATE 101
#define LIFX_LIGHT_SETCOLOR 102
#define LIFX_LIGHT_STATE 107

// Packet buffer size
#define LIFX_INCOMING_PACKET_BUFFER_LEN 600

// Length in bytes of serial numbers
#define LIFX_SERIAL_LEN 6

// An EthernetUDP instance to let us send and receive packets over UDP
WiFiUDP Udp;

unsigned long timeoutInterval = 500;

unsigned long lastSend = 0;
unsigned long lastCheck = 0;

boolean buttonState = LOW;
unsigned long onTime;
uint16_t level = 0;
uint16_t brightness = 0;
uint16_t hue = 0;
uint16_t saturation = 0;
uint16_t kelvin = 4000;

#define LEDPIN LED_BUILTIN
int buttonState = HIGH;

long lastDebounceTime = 0;
long debounceDelay = 50;
long holdWindow = 800;

int lastButtonState = HIGH;
long lastHoldTime = -1;
long lastPressTime = -1;

bool initialised = false;

void setup() {
  Serial.begin(19200);

  Serial.print("\n\n\n\n");
  Serial.println("Setting up switches");
  pinMode(buttonPin, INPUT_PULLUP);

  Serial.println("\n\nSetting up network");
  IPAddress deviceIpip(192, 168, 1, 211); //this device IP - update if you like
  IPAddress gateway(192, 168, 1, 1); //your router
  IPAddress subnet(255, 255, 255, 0);
  WiFi.config(ip, gateway, subnet);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Udp.begin(localPort); // Listen for incoming UDP packets
  Serial.println("Network is set up");
}

void loop() {
  //read the button and check for changes


  buttonState = digitalRead(buttonPin);
  if ( (millis() - lastDebounceTime) > debounceDelay) {
    if (buttonState == LOW && lastButtonState == HIGH) {
      //the button has been pressed
      lastButtonState = LOW;
      lastHoldTime = millis();
    }

    if (buttonState == HIGH && lastButtonState == LOW && (millis() - lastHoldTime < holdWindow)) {
      //the button has been released (quickly)
      lastButtonState = HIGH;
      lastDebounceTime = millis();
      if (level == 0) {
        level = 65535;
      } else {
        level = 0;
      }
      Serial.println(SetPower(dest, level));
      lastPressTime = millis();
    } else if (buttonState == HIGH && lastButtonState == LOW) {
      //the button has been released after holding for a while
      lastButtonState = HIGH;
      lastDebounceTime = millis();
    }
  }
}

uint16_t SetPower(uint8_t *dest, uint16_t power) {

  lifx_header header;
  lifx_payload_device_set_power payload;

  // Initialise both structures
  memset(&header, 0, sizeof(header));
  memset(&payload, 0, sizeof(payload));

  // Set the target the nice way
  memcpy(header.target, dest, sizeof(uint8_t) * LIFX_SERIAL_LEN);

  // Setup the header
  header.size = sizeof(lifx_header) + sizeof(payload); // Size of header + payload
  header.tagged = 0;
  header.addressable = 1;
  header.protocol = 1024;
  header.source = 123;
  header.ack_required = 1;
  //header.res_required = 1;
  header.sequence = 100;
  header.type = LIFX_DEVICE_SETPOWER;

  payload.level = power;

  // Send a packet on startup
  Udp.beginPacket(broadcast_ip, 56700);
  Udp.write((char *) &header, sizeof(lifx_header));
  Udp.write((char *) &payload, sizeof(payload));    // Which makes the data on wire correct
  Udp.endPacket();

  unsigned long started = millis();
  while (millis() - started < timeoutInterval) {
    int packetLen = Udp.parsePacket();
    byte packetBuffer[LIFX_INCOMING_PACKET_BUFFER_LEN];
    if (packetLen && packetLen < LIFX_INCOMING_PACKET_BUFFER_LEN) {
      Udp.read(packetBuffer, sizeof(packetBuffer));
      Serial.print("Received Packet type: ");
      Serial.println(((lifx_header *)packetBuffer)->type);
    }
  }
  return power;
}
2 Likes