Last active
September 13, 2021 14:36
-
-
Save erijpkema/17f2b970ca79fb7b8049e5d14bc541b2 to your computer and use it in GitHub Desktop.
ESP8266 flash lifx lights
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* This is made for a ESP8266 (i use a wemos d1). It uses the udp lan protocol to flash the lights. | |
* This program will let your lifx lamps flash purple seven times when a switch is pressed. | |
* When it has a wifi connection, a led will go on. | |
* I started from code by daniel_hall at https://community.lifx.com/t/sending-lan-packet-using-arduino/1460/3 | |
*/ | |
#include <ESP8266WiFi.h> | |
#include <WiFiUdp.h> | |
#include <ESP8266WiFiMulti.h> | |
#include <SPI.h> | |
#define pushButton 14 | |
#define readyLed 15 | |
// Remote IP (In this case we broadcast to the entire subnet) | |
IPAddress broadcast_ip(192, 168, 178, 255); | |
unsigned int localPort = 8888; // Port to listen for responses on | |
unsigned int lifxPort = 56700; // Port used to send to send to LIFX devices | |
const char* WiFiSSID = "my_ssd"; | |
const char* WiFiPW = "wifi_password"; | |
ESP8266WiFiMulti WiFiMulti; | |
WiFiUDP Udp; | |
// 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) | |
// Device::SetColor Payload | |
#pragma pack(push, 1) | |
typedef struct { | |
uint16_t level; | |
} lifx_payload_device_set_power; | |
#pragma pack(pop) | |
// see SetColor https://lan.developer.lifx.com/docs/light-messages | |
#pragma pack(push, 1) | |
typedef struct { | |
uint8_t reserved; | |
//HSBK | |
uint16_t hue; | |
uint16_t saturation; | |
uint16_t brightness; | |
uint16_t kelvin; | |
uint32_t duration; | |
} lifx_payload_light_set_color; | |
#pragma pack(pop) | |
// Payload types | |
#define LIFX_DEVICE_SETPOWER 21 | |
#define LIFX_LIGHT_SETCOLOR 102 | |
// Packet buffer size | |
#define LIFX_INCOMING_PACKET_BUFFER_LEN 300 | |
// Timing data | |
unsigned long sendInterval = 5000; // 5 seconds | |
unsigned long lastSend = 0; | |
void setup() { | |
Serial.begin(9600); | |
// Wait a little... | |
for(uint8_t t = 4; t > 0; t--) { | |
Serial.printf("[SETUP] WAIT %d...\n", t); | |
Serial.flush(); | |
delay(1000); | |
} | |
Serial.printf("Adding AP \n"); | |
WiFiMulti.addAP(WiFiSSID, WiFiPW); | |
Serial.println("DEBUG added ap"); | |
Udp.begin(localPort); // Listen for incoming UDP packets | |
Serial.println("DEBUG, listening for incoming UDB"); | |
// Setup the Pushbutton | |
// make the pushbutton's pin an input: | |
pinMode(pushButton, OUTPUT); // Output first seems to be nessecary on wemos d1. | |
pinMode(pushButton, INPUT); | |
pinMode(readyLed, OUTPUT); | |
while (WiFi.status() != WL_CONNECTED) | |
{ | |
delay(500); | |
Serial.print("."); | |
} | |
Serial.println(" connected"); | |
digitalWrite(readyLed, HIGH); | |
} | |
void set_power(const unsigned int level) { | |
lifx_header header; | |
lifx_payload_device_set_power payload; | |
// Initialise both structures | |
memset(&header, 0, sizeof(header)); | |
memset(&payload, 0, sizeof(payload)); | |
// Setup the header | |
header.size = sizeof(lifx_header) + sizeof(payload); // Size of header + payload | |
header.tagged = 1; | |
header.addressable = 1; | |
header.protocol = 1024; | |
header.source = 123; | |
header.ack_required = 1; | |
header.sequence = 100; | |
header.type = LIFX_DEVICE_SETPOWER; | |
// Setup payload | |
payload.level = level; | |
Serial.println("writing package"); | |
// Send a packet on startup | |
Udp.beginPacket(broadcast_ip, 56700); | |
Udp.write((char *) &header, sizeof(lifx_header)); // Treat the structures like byte arrays | |
Udp.write((char *) &payload, sizeof(payload)); // Which makes the data on wire correct | |
Udp.endPacket(); | |
Serial.println("package written"); | |
} | |
void set_color(const unsigned int hue, const unsigned int saturation, const unsigned int kelvin) { | |
// Set color to purple | |
lifx_header header; | |
lifx_payload_light_set_color payload; | |
// Initialise both structures | |
memset(&header, 0, sizeof(header)); | |
memset(&payload, 0, sizeof(payload)); | |
// Setup the header | |
header.size = sizeof(lifx_header) + sizeof(payload); // Size of header + payload | |
header.tagged = 1; | |
header.addressable = 1; | |
header.protocol = 1024; | |
header.source = 123; | |
header.ack_required = 1; | |
header.sequence = 100; | |
header.type = LIFX_LIGHT_SETCOLOR; | |
payload.hue = hue; // 0 - 65535 | |
payload.saturation = saturation; | |
payload.brightness = 65535; | |
payload.kelvin = kelvin; | |
Serial.println("Writing color payload"); | |
// Send a packet on startup | |
Udp.beginPacket(broadcast_ip, 56700); | |
Udp.write((char *) &header, sizeof(lifx_header)); // Treat the structures like byte arrays | |
Udp.write((char *) &payload, sizeof(payload)); // Which makes the data on wire correct | |
Udp.endPacket(); | |
Serial.println("package written"); | |
} | |
void flash () { | |
/* | |
* Flash purple three times | |
* set to white repeatedly afterwards, | |
* just to be sure. | |
*/ | |
//set purple | |
set_color(50000, 65535, 32767); | |
// flash lights 3 times | |
for(uint8_t t = 3; t > 0; t--) { | |
set_power(65535); | |
delay(2000); | |
set_power(0); | |
delay(2000); | |
} | |
delay(5000); | |
for(uint8_t t = 6; t > 0; t--) { | |
set_color(0, 0, 32767); // set white 8996k | |
set_power(65535); | |
delay(2000); | |
} | |
} | |
void loop() { | |
// read the input pin: | |
int buttonState = digitalRead(pushButton); | |
// print out the state of the button: | |
Serial.println(buttonState); | |
delay(1); // delay in between reads for stability | |
if(buttonState == 1) { | |
flash(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment