// process a packet from HQ
void leadIncoming(const char *packet, size_t len, unsigned short *index) {
  char *type, *command, *buffer;

  buffer = (char*)malloc(len);
  memcpy(buffer, packet, len);

  uint16_t to;
  unsigned long id;

  type = j0g_str("type", buffer, index);
  if (hqVerboseOutput) {
    Serial.println(type);
  }

  if (strcmp(type, "online") == 0) {
    Shell.allReportHQ();
  }

  if (strcmp(type, "command") == 0) {
    to = atoi(j0g_str("to", buffer, index));
    id = strtoul(j0g_str("id", buffer, index), NULL, 10);
    command = j0g_str("command", buffer, index);
    if (strlen(j0g_str("to", buffer, index)) == 0 || !id || !command) {
      if (hqVerboseOutput) {
        Serial.println(F("invalid command, requires to, id, command"));
        Serial.print(F("to: "));
        Serial.println(to);
        Serial.print(F("id: "));
        Serial.println(id);
        Serial.print(F("command: "));
        Serial.println(command);
      }
      free(buffer);
      return;
    }

    // handle internal ones first
    if (to == Scout.getAddress()) {
      setOutputHandler(&printToString<&leadCommandOutput>);
      doCommand(command);
      resetOutputHandler();

      StringBuffer report;
      report.appendSprintf("{\"type\":\"reply\",\"from\":%d,\"id\":%lu,\"end\":true,\"reply\":", to, id);
      report.appendJsonString(leadCommandOutput, true);
      report += "}\n";
      leadSignal(report);
      leadCommandOutput = (char*)NULL;

      free(buffer);
      return;
    }

    // we can only send one command at a time
    if (leadCommandTo) {
      // TODO we could stop reading the HQ socket in this mode and then never get a busy?
      free(buffer);
      return leadCommandError(to,id,"busy");
    }

    // send over mesh to recipient and cache id for any replies
    leadAnswerID = id;
    leadCommandTo = to;
    leadCommandChunks = command;
    leadCommandChunksAt = 0;
    leadCommandRetries = 0;
    leadCommandChunk();
  }

  free(buffer);
}
// [3,[0,1,2],[v,v,v],4]
StringBuffer ScoutHandler::report(StringBuffer &report) {
  report.setCharAt(report.length() - 1, ',');
  report.appendSprintf("%lu]",millis());
  Scout.handler.announce(0xBEEF, report);
  return report2json(report);
}