LIFX Developer Zone

UDP SetPower - broadcast IP or device IP?

Background: I have an ESP8266 board that I’m building into a bi-directional retractive light switch. After a lot of delays I’m 95% there, and I’ve just hit a really weird issue that I can’t figure out from the documentation.

On startup, my code broadcasts a GetColor (101) packet containing the mac address for each of the lights configured, and stores the returned IP for future commands.

A “click” triggers SetPower (21) for either “on” or “off” (65535 or 0)
A “hold” triggers SetColor (102) to increase or decrease the brightness value.

SetColor is definitely more reliable if I send the UDP packet to the light’s IP rather than broadcasting, which is what I’d expect (and the whole reason for storing the IP)
SetPower on the other hand? If I send the packet to the light’s IP, depending on the light I choose, I either get a massive delay (around 3 seconds in most cases) or no response whatsoever. If I broadcast it appears to work nearly instantaneously.

The basis for my UDP code is the Arduino code written here by Daniel Hall.

The specific SetPower function is as follows:

uint16_t SetPower(uint8_t *dest, uint16_t *power, IPAddress address) {
//uint16_t SetPower(uint8_t *dest, uint16_t power, IPAddress *ip) {

  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 to device IP -- not working
  // Udp.beginPacket(address, 56700); 
  // Send a packet to broadcast IP -- fallback
  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;
}

Can anyone offer any insight?

That sounds weird, I’m not sure what would be happening there.

If you download weird.py and run

python3 -m venv photons
./photons/bin/python -m pip install lifx-photons-core
./photons/bin/python weird.py

It’ll do what it sounds like you’re doing for discover (I think GetVersion would be better than GetColor if you want to use something other than GetService for discovery, comments in the script)

And then lets you choose which device you want to send power to and will send a DeviceSetPower with no retries (line 75 lets you tell it to use retries if you want to try with that, by default photons is pretty agressive with retries)

For me it’s very instant. I imagine if it’s not for you it’d be best to follow this and make a ticket so the support team can take a look.

Thanks, that seems to be working as I originally expected (although I haven’t tested it against the same light as before).

FYI I’m using GetColor because I need to initialise the values on the board so I can do dimming from their current state. I don’t have any plans to get any switches soon, not least because the UK style ones haven’t been announced yet, so I’m fairly safe from spurious messages.

A future version will add in a GetVersion or similar to give the user a nice dropdown to choose which light to control - for now I just whack the mac addresses in a json file and upload it.

Guess I need to keep fiddling for a while longer. If I get anything repeatable I’ll raise a ticket. As a professional software developer I know better than to bug the support team with unrepeatable issues that only affect me some of the time :wink:

Thanks, that seems to be working as I originally expected (although I haven’t tested it against the same light as before).

So you have the problem with your code but not my code? Or are you saying the problem has gone even with your code ?

FYI I’m using GetColor because I need to initialise the values on the board so I can do dimming from their current state.

Right, that makes sense :slight_smile:

Your code worked fine. I wasn’t able to retest my code. I’ll get back to you when I’ve got more data. It’s entirely possible something else was to blame

cool cool :slight_smile: