bool ClimateControlBehaviour::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(climatecontrol_key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Description properties
        case activeCoolingMode_key+descriptions_key_offset:
          aPropValue->setBoolValue(climateDeviceKind==climatedevice_fancoilunit); // FCUs can cool actively
          return true;
        // Settings properties
        case heatingSystemCapability_key+settings_key_offset:
          aPropValue->setUint8Value(heatingSystemCapability);
          return true;
        case heatingSystemType_key+settings_key_offset:
          aPropValue->setUint8Value(heatingSystemType);
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Settings properties
        case heatingSystemCapability_key+settings_key_offset:
          setPVar(heatingSystemCapability, (VdcHeatingSystemCapability)aPropValue->uint8Value());
          return true;
        case heatingSystemType_key+settings_key_offset:
          setPVar(heatingSystemType, (VdcHeatingSystemType)aPropValue->uint8Value());
          return true;
      }
    }
  }
  // not my field, let base class handle it
  return inherited::accessField(aMode, aPropValue, aPropertyDescriptor);
}
// access to all fields
bool ChannelBehaviour::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(channel_Key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Description properties
        case name_key+descriptions_key_offset:
          aPropValue->setStringValue(getName());
          return true;
        case channelIndex_key+descriptions_key_offset:
          aPropValue->setUint8Value(channelIndex);
          return true;
        case min_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getMin());
          return true;
        case max_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getMax());
          return true;
        case resolution_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getResolution());
          return true;
        // Settings properties
        // - none for now
        // States properties
        case value_key+states_key_offset:
          // get value of channel, possibly calculating it if needed (color conversions)
          aPropValue->setDoubleValue(getChannelValueCalculated());
          return true;
        case age_key+states_key_offset:
          if (channelLastSync==Never)
            aPropValue->setNull(); // no value known
          else
            aPropValue->setDoubleValue((double)(MainLoop::now()-channelLastSync)/Second);
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Settings properties
        // - none for now
        // States properties
        case value_key+states_key_offset:
          setChannelValue(aPropValue->doubleValue(), 0, true); // always apply, no transition time
          return true;
      }
    }
  }
  // single class level properties only, don't call inherited
  return false;
}
Exemple #3
0
ErrorPtr P44JsonApiRequest::sendResult(ApiValuePtr aResult)
{
  LOG(LOG_DEBUG, "cfg <- vdcd (JSON) result sent: result=%s", aResult ? aResult->description().c_str() : "<none>");
  JsonApiValuePtr result = boost::dynamic_pointer_cast<JsonApiValue>(aResult);
  if (result) {
    P44VdcHost::sendCfgApiResponse(jsonComm, result->jsonObject(), ErrorPtr());
  }
  else {
    // always return SOMETHING
    P44VdcHost::sendCfgApiResponse(jsonComm, JsonObject::newNull(), ErrorPtr());
  }
  return ErrorPtr();
}
Exemple #4
0
// access to all fields
bool EnoceanDevice::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(enoceanDevice_key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        case profileVariants_key:
          aPropValue->setType(apivalue_object); // make object (incoming object is NULL)
          return getProfileVariants(aPropValue);
        case profile_key:
          aPropValue->setInt32Value(getEEProfile()); return true;
        case packetage_key:
          // Note lastPacketTime is set to now at startup, so additionally check lastRSSI
          if (lastPacketTime==Never || lastRSSI<=-999)
            aPropValue->setNull();
          else
            aPropValue->setDoubleValue((double)(MainLoop::now()-lastPacketTime)/Second);
          return true;
        case rssi_key:
          if (lastRSSI<=-999)
            aPropValue->setNull();
          else
            aPropValue->setInt32Value(lastRSSI);
          return true;
        case repeaterCount_key:
          if (lastRSSI<=-999)
            aPropValue->setNull();
          else
            aPropValue->setUint8Value(lastRepeaterCount);
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        case profile_key:
          setProfileVariant(aPropValue->int32Value()); return true;
      }
    }
  }
  // not my field, let base class handle it
  return inherited::accessField(aMode, aPropValue, aPropertyDescriptor);
}
Exemple #5
0
bool EnoceanDevice::getProfileVariants(ApiValuePtr aApiObjectValue)
{
  // check if current profile is one of the interchangeable ones
  const ProfileVariantEntry *currentVariant = profileVariantsTable();
  while (currentVariant && currentVariant->profileGroup!=0) {
    // look for current EEP in the list of variants
    if (getEEProfile()==currentVariant->eep) {
      // create string from all other variants (same profileGroup), if any
      bool anyVariants = false;
      const ProfileVariantEntry *variant = profileVariantsTable();
      while (variant->profileGroup!=0) {
        if (variant->profileGroup==currentVariant->profileGroup) {
          if (variant->eep!=getEEProfile()) anyVariants = true; // another variant than just myself
          aApiObjectValue->add(string_format("%d",variant->eep), aApiObjectValue->newString(variant->description));
        }
        variant++;
      }
      // there are variants
      return anyVariants;
    }
    currentVariant++;
  }
  return false; // no variants
}
Exemple #6
0
void VdcJsonApiConnection::jsonResponseHandler(VdcApiResponseCB aResponseHandler, int32_t aResponseId, ErrorPtr &aError, JsonObjectPtr aResultOrErrorData)
{
  if (aResponseHandler) {
    // create request object just to hold the response ID
    string respId = string_format("%d", aResponseId);
    ApiValuePtr resultOrErrorData = JsonApiValue::newValueFromJson(aResultOrErrorData);
    VdcApiRequestPtr request = VdcJsonApiRequestPtr(new VdcJsonApiRequest(VdcJsonApiConnectionPtr(this), respId.c_str()));
    if (Error::isOK(aError)) {
      LOG(LOG_INFO,"vdSM -> vDC (JSON) result received: id='%s', result=%s\n", request->requestId().c_str(), resultOrErrorData ? resultOrErrorData->description().c_str() : "<none>");
    }
    else {
      LOG(LOG_INFO,"vdSM -> vDC (JSON) error received: id='%s', error=%s, errordata=%s\n", request->requestId().c_str(), aError->description().c_str(), resultOrErrorData ? resultOrErrorData->description().c_str() : "<none>");
    }
    aResponseHandler(VdcApiConnectionPtr(this), request, aError, resultOrErrorData);
  }
}
Exemple #7
0
void VdcJsonApiConnection::jsonRequestHandler(const char *aMethod, const char *aJsonRpcId, JsonObjectPtr aParams)
{
  ErrorPtr respErr;
  if (apiRequestHandler) {
    // create params API value
    ApiValuePtr params = JsonApiValue::newValueFromJson(aParams);
    VdcApiRequestPtr request;
    // create request object in case this request expects an answer
    if (aJsonRpcId) {
      // Method
      request = VdcJsonApiRequestPtr(new VdcJsonApiRequest(VdcJsonApiConnectionPtr(this), aJsonRpcId));
      LOG(LOG_INFO,"vdSM -> vDC (JSON) method call '%s' received: requestid='%s', params=%s\n", aMethod, request->requestId().c_str(), params ? params->description().c_str() : "<none>");
    }
    else {
      // Notification
      LOG(LOG_INFO,"vdSM -> vDC (JSON) notification '%s' received: params=%s\n", aMethod, params ? params->description().c_str() : "<none>");
    }
    // call handler
    apiRequestHandler(VdcJsonApiConnectionPtr(this), request, aMethod, params);
  }
}
bool SensorBehaviour::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(sensor_key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Description properties
        case sensorType_key+descriptions_key_offset:
          aPropValue->setUint16Value(sensorType);
          return true;
        case sensorUsage_key+descriptions_key_offset:
          aPropValue->setUint16Value(sensorUsage);
          return true;
        case min_key+descriptions_key_offset:
          aPropValue->setDoubleValue(min);
          return true;
        case max_key+descriptions_key_offset:
          aPropValue->setDoubleValue(max);
          return true;
        case resolution_key+descriptions_key_offset:
          aPropValue->setDoubleValue(resolution);
          return true;
        case updateInterval_key+descriptions_key_offset:
          aPropValue->setDoubleValue((double)updateInterval/Second);
          return true;
        case aliveSignInterval_key+descriptions_key_offset:
          aPropValue->setDoubleValue((double)aliveSignInterval/Second);
          return true;
        // Settings properties
        case group_key+settings_key_offset:
          aPropValue->setUint16Value(sensorGroup);
          return true;
        case minPushInterval_key+settings_key_offset:
          aPropValue->setDoubleValue((double)minPushInterval/Second);
          return true;
        case changesOnlyInterval_key+settings_key_offset:
          aPropValue->setDoubleValue((double)changesOnlyInterval/Second);
          return true;
        // States properties
        case value_key+states_key_offset:
          // value
          if (lastUpdate==Never)
            aPropValue->setNull();
          else
            aPropValue->setDoubleValue(currentValue);
          return true;
        case age_key+states_key_offset:
          // age
          if (lastUpdate==Never)
            aPropValue->setNull();
          else
            aPropValue->setDoubleValue((double)(MainLoop::now()-lastUpdate)/Second);
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Settings properties
        case group_key+settings_key_offset:
          setPVar(sensorGroup, (DsGroup)aPropValue->int32Value());
          return true;
        case minPushInterval_key+settings_key_offset:
          setPVar(minPushInterval, (MLMicroSeconds)(aPropValue->doubleValue()*Second));
          return true;
        case changesOnlyInterval_key+settings_key_offset:
          setPVar(changesOnlyInterval, (MLMicroSeconds)(aPropValue->doubleValue()*Second));
          return true;
      }
    }
  }
  // not my field, let base class handle it
  return inherited::accessField(aMode, aPropValue, aPropertyDescriptor);
}
ErrorPtr PropertyContainer::accessProperty(PropertyAccessMode aMode, ApiValuePtr aQueryObject, ApiValuePtr aResultObject, int aDomain, PropertyDescriptorPtr aParentDescriptor)
{
  ErrorPtr err;
  #if DEBUGFOCUSLOGGING
  FOCUSLOG("\naccessProperty: entered with query = %s\n", aQueryObject->description().c_str());
  if (aParentDescriptor) {
    FOCUSLOG("- parentDescriptor '%s' (%s), fieldKey=%u, objectKey=%u\n", aParentDescriptor->name(), aParentDescriptor->isStructured() ? "structured" : "scalar", aParentDescriptor->fieldKey(), aParentDescriptor->objectKey());
  }
  #endif
  // for reading, NULL query is like query { "":NULL }
  if (aQueryObject->isNull() && aMode==access_read) {
    aQueryObject->setType(apivalue_object);
    aQueryObject->add("", aQueryObject->newValue(apivalue_null));
  }
  // aApiObject must be of type apivalue_object
  if (!aQueryObject->isType(apivalue_object))
    return ErrorPtr(new VdcApiError(415, "Query or Value written must be object"));
  if (aMode==access_read) {
    if (!aResultObject)
      return ErrorPtr(new VdcApiError(415, "accessing property for read must provide result object"));
    aResultObject->setType(apivalue_object); // must be object
  }
  // Iterate trough elements of query object
  aQueryObject->resetKeyIteration();
  string queryName;
  ApiValuePtr queryValue;
  string errorMsg;
  while (aQueryObject->nextKeyValue(queryName, queryValue)) {
    FOCUSLOG("- starting to process query element named '%s' : %s\n", queryName.c_str(), queryValue->description().c_str());
    if (aMode==access_read && queryName=="#") {
      // asking for number of elements at this level -> generate and return int value
      queryValue = queryValue->newValue(apivalue_int64); // integer
      queryValue->setInt32Value(numProps(aDomain, aParentDescriptor));
      aResultObject->add(queryName, queryValue);
    }
    else {
      // accessing an element or series of elements at this level
      bool wildcard = isMatchAll(queryName);
      // - find all descriptor(s) for this queryName
      PropertyDescriptorPtr propDesc;
      int propIndex = 0;
      bool foundone = false;
      do {
        propDesc = getDescriptorByName(queryName, propIndex, aDomain, aParentDescriptor);
        if (propDesc) {
          foundone = true; // found at least one descriptor for this query element
          FOCUSLOG("  - processing descriptor '%s' (%s), fieldKey=%u, objectKey=%u\n", propDesc->name(), propDesc->isStructured() ? "structured" : "scalar", propDesc->fieldKey(), propDesc->objectKey());
          // actually access by descriptor
          if (propDesc->isStructured()) {
            ApiValuePtr subQuery;
            // property is a container. Now check the value
            if (queryValue->isType(apivalue_object)) {
              subQuery = queryValue; // query specifies next level, just use it
            }
            else if (queryName!="*" && (!wildcard || propDesc->isWildcardAddressable())) {
              // don't recurse deeper when query name is "*" or property is not wildcard-adressable
              // special case is "*" as leaf in query - only recurse if it is not present
              // - autocreate subquery
              subQuery = queryValue->newValue(apivalue_object);
              subQuery->add("", queryValue->newValue(apivalue_null));
            }
            if (subQuery) {
              // addressed property is a container by itself -> recurse
              // - get the PropertyContainer
              int containerDomain = aDomain; // default to same, but getContainer may modify it
              PropertyDescriptorPtr containerPropDesc = propDesc;
              PropertyContainerPtr container = getContainer(containerPropDesc, containerDomain);
              if (container) {
                FOCUSLOG("  - container for '%s' is 0x%p\n", propDesc->name(), container.get());
                FOCUSLOG("    >>>> RECURSING into accessProperty()\n");
                if (aMode==access_read) {
                  // read needs a result object
                  ApiValuePtr resultValue = queryValue->newValue(apivalue_object);
                  err = container->accessProperty(aMode, subQuery, resultValue, containerDomain, containerPropDesc);
                  if (Error::isOK(err)) {
                    // add to result with actual name (from descriptor)
                    FOCUSLOG("\n  <<<< RETURNED from accessProperty() recursion\n");
                    FOCUSLOG("  - accessProperty of container for '%s' returns %s\n", propDesc->name(), resultValue->description().c_str());
                    aResultObject->add(propDesc->name(), resultValue);
                  }
                }
                else {
                  // for write, just pass the query value
                  err = container->accessProperty(aMode, subQuery, ApiValuePtr(), containerDomain, containerPropDesc);
                  FOCUSLOG("    <<<< RETURNED from accessProperty() recursion\n", propDesc->name(), container.get());
                }
                if ((aMode!=access_read) && Error::isOK(err)) {
                  // give this container a chance to post-process write access
                  err = writtenProperty(aMode, propDesc, aDomain, container);
                }
                // 404 errors are collected, but dont abort the query
                if (Error::isError(err, VdcApiError::domain(), 404)) {
                  if (!errorMsg.empty()) errorMsg += "; ";
                  errorMsg += string_format("Error(s) accessing subproperties of '%s' : { %s }", queryName.c_str(), err->description().c_str());
                  err.reset(); // forget the error on this level
                }
              }
            }
          }
          else {
            // addressed (and known by descriptor!) property is a simple value field -> access it
            if (aMode==access_read) {
              // read access: create a new apiValue and have it filled
              ApiValuePtr fieldValue = queryValue->newValue(propDesc->type()); // create a value of correct type to get filled
              bool accessOk = accessField(aMode, fieldValue, propDesc); // read
              // for read, not getting an OK from accessField means: property does not exist (even if known per descriptor),
              // so it will not be added to the result
              if (accessOk) {
                // add to result with actual name (from descriptor)
                aResultObject->add(propDesc->name(), fieldValue);
              }
              FOCUSLOG("    - accessField for '%s' returns %s\n", propDesc->name(), fieldValue->description().c_str());
            }
            else {
              // write access: just pass the value
              if (!accessField(aMode, queryValue, propDesc)) { // write
                err = ErrorPtr(new VdcApiError(403,string_format("Write access to '%s' denied", propDesc->name())));
              }
            }
          }
        }
        else {
          // no descriptor found for this query element
          // Note: this means that property is not KNOWN, which IS not the same as getting false from accessField
          //   (latter means that property IS known, but has no value in the context it was queried)
          //   HOWEVER, for the vdc API it was decided that for reading, these cases should NOT be
          //   distinguished for getProperty. If a property does not exist for either reason, the return tree just does
          //   no contain that property.
          //   Also note that not having a property is not the same as not having a property VALUE:
          //   latter case will explicitly return a NULL value
          if (!wildcard && !foundone && aMode!=access_read) {
            // query did address a specific property but it is unknown -> report as error (for read AND write!)
            // - collect error message, but do not abort query processing
            if (!errorMsg.empty()) errorMsg += "; ";
            errorMsg += string_format("Unknown property '%s' -> ignored", queryName.c_str());
          }
        }
      } while (Error::isOK(err) && propIndex!=PROPINDEX_NONE);
    }
    // now generate error if we have collected a non-empty error message
    if (!errorMsg.empty()) {
      err = ErrorPtr(new VdcApiError(404,errorMsg));
    }
    #if DEBUGLOGGING
    if (aMode==access_read) {
      FOCUSLOG("- query element named '%s' now has result object: %s\n", queryName.c_str(), aResultObject->description().c_str());
    }
    #endif
  }
  return err;
}
Exemple #10
0
ErrorPtr DaliDeviceContainer::handleMethod(VdcApiRequestPtr aRequest, const string &aMethod, ApiValuePtr aParams)
{
  ErrorPtr respErr;
  if (aMethod=="x-p44-groupDevices") {
    // create a composite device out of existing single-channel ones
    ApiValuePtr components;
    long long collectionID = -1;
    DeviceVector groupedDevices;
    respErr = checkParam(aParams, "members", components);
    if (Error::isOK(respErr)) {
      if (components->isType(apivalue_object)) {
        components->resetKeyIteration();
        string dimmerType;
        ApiValuePtr o;
        while (components->nextKeyValue(dimmerType, o)) {
          DsUid memberUID;
          memberUID.setAsBinary(o->binaryValue());
          bool deviceFound = false;
          // search for this device
          for (DeviceVector::iterator pos = devices.begin(); pos!=devices.end(); ++pos) {
            // only non-grouped DALI devices can be grouped
            DaliDevicePtr dev = boost::dynamic_pointer_cast<DaliDevice>(*pos);
            if (dev && dev->getDsUid() == memberUID) {
              deviceFound = true;
              // found this device, create DB entry for it
              db.executef(
                "INSERT OR REPLACE INTO compositeDevices (dimmerUID, dimmerType, collectionID) VALUES ('%s','%s',%lld)",
                memberUID.getString().c_str(),
                dimmerType.c_str(),
                collectionID
              );
              if (collectionID<0) {
                // use rowid of just inserted item as collectionID
                collectionID = db.last_insert_rowid();
                // - update already inserted first record
                db.executef(
                  "UPDATE compositeDevices SET collectionID=%lld WHERE ROWID=%lld",
                  collectionID,
                  collectionID
                );
              }
              // remember
              groupedDevices.push_back(dev);
              // done
              break;
            }
          }
          if (!deviceFound) {
            respErr = ErrorPtr(new WebError(404, "some devices of the group could not be found"));
            break;
          }
        }
        if (Error::isOK(respErr) && groupedDevices.size()>0) {
          // all components inserted into DB
          // - remove grouped single devices
          for (DeviceVector::iterator pos = groupedDevices.begin(); pos!=groupedDevices.end(); ++pos) {
            (*pos)->hasVanished(false); // vanish, but keep settings
          }
          // - re-collect devices to find grouped composite now, but only in a second starting from main loop, not from here
          CompletedCB cb = boost::bind(&DaliDeviceContainer::groupCollected, this, aRequest);
          MainLoop::currentMainLoop().executeOnce(boost::bind(&DaliDeviceContainer::collectDevices, this, cb, false, false), 1*Second);
        }
      }
    }
  }
  else {
    respErr = inherited::handleMethod(aRequest, aMethod, aParams);
  }
  return respErr;
}
Exemple #11
0
// access to all fields
bool ChannelBehaviour::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(channel_Key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Description properties
        case name_key+descriptions_key_offset:
          aPropValue->setStringValue(getName());
          return true;
        case channelIndex_key+descriptions_key_offset:
          if (aPropertyDescriptor->getApiVersion()>=3) return false; // property does not exist any more in v3 and later
          aPropValue->setUint8Value(channelIndex);
          return true;
        case dsIndex_key+descriptions_key_offset:
          aPropValue->setUint8Value(channelIndex);
          return true;
        case channelType_key+descriptions_key_offset:
          aPropValue->setUint8Value(getChannelType());
          return true;
        case siunit_key+descriptions_key_offset:
          aPropValue->setStringValue(valueUnitName(getChannelUnit(), false));
          return true;
        case unitsymbol_key+descriptions_key_offset:
          aPropValue->setStringValue(valueUnitName(getChannelUnit(), true));
          return true;
        case min_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getMin());
          return true;
        case max_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getMax());
          return true;
        case resolution_key+descriptions_key_offset:
          aPropValue->setDoubleValue(getResolution());
          return true;
        // Settings properties
        // - none for now
        // States properties
        case value_key+states_key_offset:
          // get value of channel, possibly calculating it if needed (color conversions)
          aPropValue->setDoubleValue(getChannelValueCalculated());
          return true;
        case age_key+states_key_offset:
          if (channelLastSync==Never)
            aPropValue->setNull(); // no value known
          else
            aPropValue->setDoubleValue((double)(MainLoop::now()-channelLastSync)/Second); // time of last sync (does not necessarily relate to currently visible "value", as this might be a to-be-applied new value already)
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Settings properties
        // - none for now
        // States properties
        case value_key+states_key_offset:
          setChannelValue(aPropValue->doubleValue(), output.transitionTime, true); // always apply, default transition time (normally 0, unless set in outputState)
          return true;
      }
    }
  }
  // single class level properties only, don't call inherited
  return false;
}
Exemple #12
0
ApiValuePtr JsonApiValue::newValue(ApiValueType aObjectType)
{
  ApiValuePtr newVal = ApiValuePtr(new JsonApiValue);
  newVal->setType(aObjectType);
  return newVal;
}
Exemple #13
0
ErrorPtr VdcJsonApiConnection::sendRequest(const string &aMethod, ApiValuePtr aParams, VdcApiResponseCB aResponseHandler)
{
  JsonApiValuePtr params = boost::dynamic_pointer_cast<JsonApiValue>(aParams);
  ErrorPtr err;
  if (aResponseHandler) {
    // method call expecting response
    err = jsonRpcComm->sendRequest(aMethod.c_str(), params->jsonObject(), boost::bind(&VdcJsonApiConnection::jsonResponseHandler, this, aResponseHandler, _1, _2, _3));
    LOG(LOG_INFO,"vdSM <- vDC (JSON) method call sent: requestid='%d', method='%s', params=%s\n", jsonRpcComm->lastRequestId(), aMethod.c_str(), aParams ? aParams->description().c_str() : "<none>");
  }
  else {
    // notification
    err = jsonRpcComm->sendRequest(aMethod.c_str(), params->jsonObject(), NULL);
    LOG(LOG_INFO,"vdSM <- vDC (JSON) notification sent: method='%s', params=%s\n", aMethod.c_str(), aParams ? aParams->description().c_str() : "<none>");
  }
  return err;
}
Exemple #14
0
ErrorPtr VdcJsonApiRequest::sendResult(ApiValuePtr aResult)
{
  LOG(LOG_INFO,"vdSM <- vDC (JSON) result sent: requestid='%s', result=%s\n", requestId().c_str(), aResult ? aResult->description().c_str() : "<none>");
  JsonApiValuePtr result = boost::dynamic_pointer_cast<JsonApiValue>(aResult);
  return jsonConnection->jsonRpcComm->sendResult(requestId().c_str(), result ? result->jsonObject() : NULL);
}
Exemple #15
0
// access to vdc API methods and notifications via web requests
ErrorPtr P44VdcHost::processVdcRequest(JsonCommPtr aJsonComm, JsonObjectPtr aRequest)
{
  ErrorPtr err;
  string cmd;
  bool isMethod = false;
  // get method/notification and params
  JsonObjectPtr m = aRequest->get("method");
  if (m) {
    // is a method call, expects answer
    isMethod = true;
  }
  else {
    // not method, may be notification
    m = aRequest->get("notification");
  }
  if (!m) {
    err = Error::err<P44VdcError>(400, "invalid request, must specify 'method' or 'notification'");
  }
  else {
    // get method/notification name
    cmd = m->stringValue();
    // get params
    // Note: the "method" or "notification" param will also be in the params, but should not cause any problem
    ApiValuePtr params = JsonApiValue::newValueFromJson(aRequest);
    P44JsonApiRequestPtr request = P44JsonApiRequestPtr(new P44JsonApiRequest(aJsonComm));
    if (Error::isOK(err)) {
      // operation method
      if (isMethod) {
        // create request
        // check for old-style name/index and generate basic query (1 or 2 levels)
        ApiValuePtr query = params->newObject();
        ApiValuePtr name = params->get("name");
        if (name) {
          ApiValuePtr index = params->get("index");
          ApiValuePtr subquery = params->newNull();
          if (index) {
            // subquery
            subquery->setType(apivalue_object);
            subquery->add(index->stringValue(), subquery->newNull());
          }
          string nm = trimWhiteSpace(name->stringValue()); // to allow a single space for deep recursing wildcard
          query->add(nm, subquery);
          params->add("query", query);
        }
        // have method handled
        err = handleMethodForParams(request, cmd, params);
        // Note: if method returns NULL, it has sent or will send results itself.
        //   Otherwise, even if Error is ErrorOK we must send a generic response
      }
      else {
        // handle notification
        err = handleNotificationForParams(request->connection(), cmd, params);
        // Notifications are always immediately confirmed, so make sure there's an explicit ErrorOK
        if (!err) {
          err = ErrorPtr(new Error(Error::OK));
        }
      }
    }
  }
  // returning NULL means caller should not do anything more
  // returning an Error object (even ErrorOK) means caller should return status
  return err;
}
Exemple #16
0
bool OutputBehaviour::accessField(PropertyAccessMode aMode, ApiValuePtr aPropValue, PropertyDescriptorPtr aPropertyDescriptor)
{
  if (aPropertyDescriptor->hasObjectKey(output_groups_key)) {
    if (aMode==access_read) {
      // read group membership
      if (isMember((DsGroup)aPropertyDescriptor->fieldKey())) {
        aPropValue->setBoolValue(true);
        return true;
      }
      return false;
    }
    else {
      // write group
      setGroupMembership((DsGroup)aPropertyDescriptor->fieldKey(), aPropValue->boolValue());
      return true;
    }
  }
  else if (aPropertyDescriptor->hasObjectKey(output_key)) {
    if (aMode==access_read) {
      // read properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Description properties
        case outputFunction_key+descriptions_key_offset:
          aPropValue->setUint8Value(outputFunction);
          return true;
        case outputUsage_key+descriptions_key_offset:
          aPropValue->setUint16Value(outputUsage);
          return true;
        case variableRamp_key+descriptions_key_offset:
          aPropValue->setBoolValue(variableRamp);
          return true;
        case maxPower_key+descriptions_key_offset:
          aPropValue->setDoubleValue(maxPower);
          return true;
        // Settings properties
        case mode_key+settings_key_offset:
          aPropValue->setUint8Value(actualOutputMode()); // return actual mode, never outputmode_default
          return true;
        case pushChanges_key+settings_key_offset:
          aPropValue->setBoolValue(pushChanges);
          return true;
        // State properties
        case localPriority_key+states_key_offset:
          aPropValue->setBoolValue(localPriority);
          return true;
      }
    }
    else {
      // write properties
      switch (aPropertyDescriptor->fieldKey()) {
        // Settings properties
        case mode_key+settings_key_offset:
          setOutputMode((DsOutputMode)aPropValue->int32Value());
          return true;
        case pushChanges_key+settings_key_offset:
          setPVar(pushChanges, aPropValue->boolValue());
          return true;
        // State properties
        case localPriority_key+states_key_offset:
          setPVar(localPriority, aPropValue->boolValue());
          return true;
      }
    }
  }
  // not my field, let base class handle it
  return inherited::accessField(aMode, aPropValue, aPropertyDescriptor);
}