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 ArClientHandlerConfig::saveConfigToServer(
	  ArConfig *config, 
	  const std::set<std::string, ArStrCaseCmpOp> *ignoreTheseSections)
{
  //ArConfigArg param;
  ArClientArg clientArg;

  ArNetPacket sending;
  ArLog::log(ArLog::Normal, "%sSaving config to server", myLogPrefix.c_str());

  myDataMutex.lock();
  std::list<ArConfigSection *> *sections = config->getSections();
  for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); 
       sIt != sections->end(); 
       sIt++)
  {
    ArConfigSection *section = (*sIt);
    // if we're ignoring sections and we're ignoring this one, then
    // don't send it
    if (ignoreTheseSections != NULL && 
	(ignoreTheseSections->find(section->getName()) != 
	 ignoreTheseSections->end()))
    {
      ArLog::log(ArLog::Verbose, "Not sending section %s", 
		 section->getName());
      continue;
    }
    sending.strToBuf("Section");
    sending.strToBuf(section->getName());
    std::list<ArConfigArg> *params = section->getParams();

    for (std::list<ArConfigArg>::iterator pIt = params->begin(); 
         pIt != params->end(); 
         pIt++)
    {
      ArConfigArg &param = (*pIt);

      if (!clientArg.isSendableParamType(param)) {
        continue;
      }

      sending.strToBuf(param.getName());

      clientArg.argTextToBuf(param, &sending);

    } // end for each param
  } // end for each section

  myDataMutex.unlock();
  myClient->requestOnce("setConfig", &sending);
}
AREXPORT void ArServerHandlerConfig::getConfigDefaults(ArServerClient *client, 
                                                       ArNetPacket *packet)
{
  char sectionRequested[512];
  sectionRequested[0] = '\0';
  ArNetPacket sending;

  if (myDefault == NULL)
  {
    ArLog::log(ArLog::Normal, "ArServerHandlerConfig::getConfigDefaults: No default config to get");
    client->sendPacketTcp(&sending);
    return;
  }
  myConfigMutex.lock();
  // if we have a section name pick it up, otherwise we send everything
  if (packet->getDataReadLength() < packet->getDataLength())
    packet->bufToStr(sectionRequested, sizeof(sectionRequested));

  //ArConfigArg param;

  ArClientArg clientArg;

  if (sectionRequested[0] == '\0')
    ArLog::log(ArLog::Normal, "Sending all defaults to client");
  else
    ArLog::log(ArLog::Normal, "Sending defaults for section '%s' to client",
               sectionRequested);


  std::list<ArConfigSection *> *sections = myDefault->getSections();

  for (std::list<ArConfigSection *>::iterator sIt = sections->begin(); 
       sIt != sections->end(); 
       sIt++)
  {
    ArConfigSection *section = (*sIt);

    if (section == NULL) {
      continue; // Should never happen...
    }

    // if we're not sending them all and not in the right section just cont
    if (sectionRequested[0] != '\0' &&
        ArUtil::strcasecmp(sectionRequested, section->getName()) != 0) {
      continue;
    }

    sending.strToBuf("Section");
    sending.strToBuf(section->getName());

    std::list<ArConfigArg> *params = section->getParams();

    for (std::list<ArConfigArg>::iterator pIt = params->begin(); 
         pIt != params->end(); 
         pIt++)
    {
      ArConfigArg &param = (*pIt);

      if (!clientArg.isSendableParamType(param)) {
        continue;
      }

      sending.strToBuf(param.getName());
      clientArg.argTextToBuf(param, &sending);

    } // end for each param
  } // end for each section
  myConfigMutex.unlock();

  client->sendPacketTcp(&sending);
}
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
AREXPORT void ArServerHandlerCameraCollection::getCameraList(ArServerClient *client,
        ArNetPacket *packet)
{
    if (client == NULL) {
        return; // Something very bad has happened...
    }

    ArNetPacket sendPacket;

    if (myCameraCollection == NULL) {
        sendPacket.byte2ToBuf(0);
        client->sendPacketTcp(&sendPacket);
    }

    // This lack of recursive locks is troublesome... Data might
    // change between calls...

    std::list<std::string> cameraNames;
    myCameraCollection->getCameraNames(cameraNames);

    sendPacket.byte2ToBuf(cameraNames.size());

    for (std::list<std::string>::iterator iter = cameraNames.begin();
            iter != cameraNames.end();
            iter++) {

        const char *curName = iter->c_str();

        sendPacket.strToBuf(curName);

        // TODO: ArNetPacket will NOT behave correctly if the given str is NULL
        // Fix this somehow...

        sendPacket.strToBuf(myCameraCollection->getCameraType(curName));
        sendPacket.strToBuf(myCameraCollection->getDisplayName(curName));
        sendPacket.strToBuf(myCameraCollection->getDisplayType(curName));

        // Send commands...

        std::list<std::string> commands;
        myCameraCollection->getCameraCommands(curName, commands);

        sendPacket.byte2ToBuf(commands.size());

        for (std::list<std::string>::iterator comIter = commands.begin();
                comIter != commands.end();
                comIter++) {

            const char *curCommand = comIter->c_str();

            sendPacket.strToBuf(curCommand);
            sendPacket.strToBuf(myCameraCollection->getCommandName(curName, curCommand));
            sendPacket.byte4ToBuf(myCameraCollection->getRequestInterval(curName, curCommand));

        } // end for each command

        // Send parameters...

        std::list<std::string> params;
        myCameraCollection->getParameterNames(curName, params);

        sendPacket.byte2ToBuf(params.size());

        ArConfigArg arg;
        ArClientArg clientArg;

        bool isSuccess = true;

        for (std::list<std::string>::iterator paramIter = params.begin();
                paramIter != params.end();
                paramIter++) {

            const char *paramName = paramIter->c_str();

            isSuccess = myCameraCollection->getParameter(curName,
                        paramName,
                        arg);
            if (!isSuccess) {
                ArLog::log(ArLog::Normal,
                           "ArServerHandlerCameraCollection::getCameraList() could not find param %s", paramName);
                continue;
            }

            // Add the current parameter to the packet
            isSuccess = clientArg.createPacket(arg, &sendPacket);

        } // end for each parameter

    } // end for each camera

    client->sendPacketTcp(&sendPacket);

} // end method getCameraList