void PtzCameraExample::handleCameraListReply(ArNetPacket *pkt)
{
  ArTypes::Byte2 numCams = pkt->bufToByte2();
  ArLog::log(ArLog::Normal, "%d cameras in list.", numCams);
  char camName[128];
  char camType[128];
  char displayName[128];
  char displayType[128];
  char cmdDesc[128];
  char cmdName[128];
  ArTypes::Byte4 cmdFreq;
  int dataReqFreq = 100;
  for(ArTypes::Byte2 i = 0; i < numCams; ++i)
  {
    memset(camName, 0, 128);
    memset(camType, 0, 128);
    memset(displayName, 0, 128);
    memset(displayType, 0, 128);
    pkt->bufToStr(camName, 128); // name

    ArClientHandlerCamera *cam = new ArClientHandlerCamera(myClient, camName);

    pkt->bufToStr(camType, 128); // type
    cam->type = camType;
    pkt->bufToStr(displayName, 128); // description
    cam->displayName = displayName;
    pkt->bufToStr(displayType, 128); // description
    cam->displayType = displayType;
    ArTypes::Byte2 numCmds = pkt->bufToByte2();
    ArLog::log(ArLog::Normal, "%d commands for camera \'%s\' (%s) / \'%s\' (%s)", numCmds, camName, camType, displayName, displayType);
    for(ArTypes::Byte2 c = 0; c < numCmds; ++c)
    {
      memset(cmdDesc, 0, 128);
      memset(cmdName, 0, 128);
      char cmdDesc[128];
      char cmdName[128];
      pkt->bufToStr(cmdDesc, 128); // description
      pkt->bufToStr(cmdName, 128); // request name
      cmdFreq = pkt->bufToByte4(); // recommended request frequency
      ArLog::log(ArLog::Normal, "Camera %s has %s command named %s with recommended request frequency %d.", camName, cmdDesc, cmdName, cmdFreq);

      if(strcmp(cmdDesc, "getCameraData") == 0)
        dataReqFreq = cmdFreq;
    }
    ArTypes::Byte2 numParams = pkt->bufToByte2();
    ArLog::log(ArLog::Normal, "Camera %s has %d parameters.", camName, numParams);
    for(ArTypes::Byte2 p = 0; p < numParams; ++p)
    {
      ArClientArg carg;
      ArConfigArg arg;
      if(!carg.bufToArgValue(pkt, arg))
        ArLog::log(ArLog::Normal, "Hmm, error getting ArClientArg for camera %s's parameter #%d.", camName, p);
    }

    cam->requestUpdates(dataReqFreq);
    mutex.lock();
    myCameras.insert(cam);
    mutex.unlock();
  }
}
AREXPORT void ArServerHandlerCameraCollection::setParams(ArServerClient *client,
        ArNetPacket *packet)
{
    if ((packet == NULL) || (myCameraCollection == NULL)) {
        return;
    }
    char buffer[512];

    packet->bufToStr(buffer, sizeof(buffer));
    std::string cameraName = buffer;

    ArNetPacket paramUpdatedPacket;
    paramUpdatedPacket.strToBuf(cameraName.c_str());

    ArConfigArg arg;
    ArClientArg clientArg;
    bool isSuccess = true;
    bool isParamUpdated = false;

    bool isDone = false;

    while (!isDone) {

        packet->bufToStr(buffer, sizeof(buffer));
        std::string paramName = buffer;

        if (paramName.empty()) {
            isDone = true;
            break;
        }

        isSuccess = myCameraCollection->getParameter(cameraName.c_str(),
                    paramName.c_str(),
                    arg);

        if (!isSuccess) {
            ArLog::log(ArLog::Verbose,
                       "ArServerHandlerCameraCollection::setParams() could not find camera %s, param %s",
                       cameraName.c_str(), paramName.c_str());
            continue;
        }

        isSuccess = clientArg.bufToArgValue(packet, arg);

        if (!isSuccess) {
            continue;
        }

        isSuccess = myCameraCollection->setParameter(cameraName.c_str(), arg);

        if (!isSuccess) {
            continue;
        }

        paramUpdatedPacket.strToBuf(arg.getName());
        clientArg.argValueToBuf(arg, &paramUpdatedPacket);
        isParamUpdated = true;

    } // end for each param

    // TODO Send a confirmation back, or just use the broadcast packet?  (If a, then add
    // client to broadcast)

    // Add an empty string to indicate the last parameter...
    paramUpdatedPacket.strToBuf("");

    // Haven't quite decided whether to send the update packet, or a success/error notice...
    client->sendPacketTcp(&paramUpdatedPacket);


    if (isParamUpdated) {
        // NOT_EXCLUDING this used to not send it to the client, but no
        // longer has that behavior since it causes problems with the
        // central server
        myServer->broadcastPacketTcp(&paramUpdatedPacket,
                                     PARAMS_UPDATED_PACKET_NAME);
    }

    /**
    // TODO: Add error message?
    ArNetPacket retPacket;
    retPacket->strToBuf("");
    client->sendPacketTcp(&retPacket);
    **/

} // end method setParams