Exemple #1
0
void AnalogIODevice::applyChannelValues(SimpleCB aDoneCB, bool aForDimming)
{
  MLMicroSeconds transitionTime = 0;
  // abort previous transition
  MainLoop::currentMainLoop().cancelExecutionTicket(timerTicket);
  // generic device, show changed channels
  if (analogIOType==analogio_dimmer) {
    // single channel PWM dimmer
    LightBehaviourPtr l = boost::dynamic_pointer_cast<LightBehaviour>(output);
    if (l && l->brightnessNeedsApplying()) {
      transitionTime = l->transitionTimeToNewBrightness();
      l->brightnessTransitionStep(); // init
      applyChannelValueSteps(aForDimming, transitionTime==0 ? 1 : (double)TRANSITION_STEP_TIME/transitionTime);
    }
    // consider applied
    l->brightnessApplied();
  }
  else if (analogIOType==analogio_rgbdimmer) {
    // three channel RGB PWM dimmer
    RGBColorLightBehaviourPtr cl = boost::dynamic_pointer_cast<RGBColorLightBehaviour>(output);
    if (cl) {
      if (needsToApplyChannels()) {
        // needs update
        // - derive (possibly new) color mode from changed channels
        cl->deriveColorMode();
        // - calculate and start transition
        //   TODO: depending to what channel has changed, take transition time from that channel. For now always using brightness transition time
        transitionTime = cl->transitionTimeToNewBrightness();
        cl->brightnessTransitionStep(); // init
        cl->colorTransitionStep(); // init
        applyChannelValueSteps(aForDimming, transitionTime==0 ? 1 : (double)TRANSITION_STEP_TIME/transitionTime);
      } // if needs update
      // consider applied
      cl->appliedColorValues();
    }
  }
  else {
    // direct single channel PWM output, no smooth transitions
    ChannelBehaviourPtr ch = getChannelByIndex(0);
    if (ch && ch->needsApplying()) {
      double chVal = ch->getTransitionalValue()-ch->getMin();
      double chSpan = ch->getMax()-ch->getMin();
      analogIO->setValue(chVal/chSpan*100); // 0..100%
      ch->channelValueApplied(); // confirm having applied the value
    }
  }
  // always consider apply done, even if transition is still running
  inherited::applyChannelValues(aDoneCB, aForDimming);
}
Exemple #2
0
DemoDevice::DemoDevice(DemoDeviceContainer *aClassContainerP) :
  Device((DeviceClassContainer *)aClassContainerP)
{
  // a demo device is a light which shows its dimming value as a string of 0..50 hashes on the console
  // - is a light device
  primaryGroup = group_yellow_light;
  // - use light settings, which include a fully functional scene table
  installSettings(DeviceSettingsPtr(new LightDeviceSettings(*this)));
  // - create one output with light behaviour
  LightBehaviourPtr l = LightBehaviourPtr(new LightBehaviour(*this));
  // - set default config to act as dimmer with variable ramps
  l->setHardwareOutputConfig(outputFunction_dimmer, usage_undefined, true, -1);
  addBehaviour(l);
  // - hardware is defined, now derive dSUID
	deriveDsUid();
}
void DigitalIODevice::applyChannelValues(SimpleCB aDoneCB, bool aForDimming)
{
  LightBehaviourPtr lightBehaviour = boost::dynamic_pointer_cast<LightBehaviour>(output);
  if (lightBehaviour) {
    // light
    if (lightBehaviour->brightnessNeedsApplying()) {
      indicatorOutput->set(lightBehaviour->brightnessForHardware());
      lightBehaviour->brightnessApplied(); // confirm having applied the value
    }
  }
  else if (output) {
    // simple switch output, activates at 50% of possible output range
    ChannelBehaviourPtr ch = output->getChannelByIndex(0);
    if (ch->needsApplying()) {
      indicatorOutput->set(ch->getChannelValue() >= (ch->getMax()-ch->getMin())/2);
      ch->channelValueApplied();
    }
  }
  inherited::applyChannelValues(aDoneCB, aForDimming);
}
Exemple #4
0
void OlaDevice::applyChannelValues(SimpleCB aDoneCB, bool aForDimming)
{
  MLMicroSeconds transitionTime = 0;
  // abort previous transition
  MainLoop::currentMainLoop().cancelExecutionTicket(transitionTicket);
  // generic device, show changed channels
  if (olaType==ola_dimmer) {
    // single channel dimmer
    LightBehaviourPtr l = boost::dynamic_pointer_cast<LightBehaviour>(output);
    if (l && l->brightnessNeedsApplying()) {
      transitionTime = l->transitionTimeToNewBrightness();
      l->brightnessTransitionStep(); // init
      applyChannelValueSteps(aForDimming, transitionTime==0 ? 1 : (double)TRANSITION_STEP_TIME/transitionTime);
    }
    // consider applied
    l->brightnessApplied();
  }
  else if (olaType==ola_fullcolordimmer) {
    // RGB, RGBW or RGBWA dimmer
    RGBColorLightBehaviourPtr cl = boost::dynamic_pointer_cast<RGBColorLightBehaviour>(output);
    if (cl) {
      MovingLightBehaviourPtr ml = boost::dynamic_pointer_cast<MovingLightBehaviour>(output);
      if (needsToApplyChannels()) {
        // needs update
        // - derive (possibly new) color mode from changed channels
        cl->deriveColorMode();
        // - calculate and start transition
        //   TODO: depending to what channel has changed, take transition time from that channel. For now always using brightness transition time
        transitionTime = cl->transitionTimeToNewBrightness();
        cl->brightnessTransitionStep(); // init
        cl->colorTransitionStep(); // init
        if (ml) ml->positionTransitionStep(); // init
        applyChannelValueSteps(aForDimming, transitionTime==0 ? 1 : (double)TRANSITION_STEP_TIME/transitionTime);
      }
      // consider applied
      if (ml) ml->appliedPosition();
      cl->appliedColorValues();
    }
  }
  inherited::applyChannelValues(aDoneCB, aForDimming);
}
Exemple #5
0
void DemoDevice::applyChannelValues(SimpleCB aDoneCB, bool aForDimming)
{
  // light device
  LightBehaviourPtr lightBehaviour = boost::dynamic_pointer_cast<LightBehaviour>(output);
  if (lightBehaviour && lightBehaviour->brightnessNeedsApplying()) {
    // This would be the place to implement sending the output value to the hardware
    // For the demo device, we show the output as a bar of 0..64 '#' chars
    // - read the brightness value from the behaviour
    int hwValue = lightBehaviour->brightnessForHardware();
    // - display as a bar of hash chars
    string bar;
    while (hwValue>0) {
      // one hash character per 2 output value steps (0..100 = 0..50 hashes)
      bar += '#';
      hwValue -= 2;
    }
    printf("Demo Device Output: %s\n", bar.c_str());
    lightBehaviour->brightnessApplied(); // confirm having applied the value
  }
  inherited::applyChannelValues(aDoneCB, aForDimming);
}
Exemple #6
0
OlaDevice::OlaDevice(OlaDeviceContainer *aClassContainerP, const string &aDeviceConfig) :
  inherited(aClassContainerP),
  olaType(ola_unknown),
  whiteChannel(dmxNone),
  redChannel(dmxNone),
  greenChannel(dmxNone),
  blueChannel(dmxNone),
  amberChannel(dmxNone),
  transitionTicket(0)
{
  // evaluate config
  string config = aDeviceConfig;
  string mode = "dimmer"; // default to dimmer
  size_t i = aDeviceConfig.find(":");
  if (i!=string::npos) {
    mode = aDeviceConfig.substr(0,i);
    config = aDeviceConfig.substr(i+1,string::npos);
  }
  if (mode=="dimmer")
    olaType = ola_dimmer;
  else if (mode=="tunablewhite")
    olaType = ola_tunablewhitedimmer;
  else if (mode=="color")
    olaType = ola_fullcolordimmer;
  else {
    LOG(LOG_ERR, "unknown OLA device type: %s", mode.c_str());
  }
  // by default, act as black device so we can configure colors
  primaryGroup = group_black_joker;
  // get DMX channels specifications
  char channelType;
  DmxChannel channelNo;
  DmxValue defaultValue;
  size_t p = 0;
  while (nextChannelSpec(config, p, channelType, channelNo, defaultValue)) {
    switch (channelType) {
      case 'W' : whiteChannel = channelNo; break;
      case 'R' : redChannel = channelNo; break;
      case 'G' : greenChannel = channelNo; break;
      case 'B' : blueChannel = channelNo; break;
      case 'A' : amberChannel = channelNo; break;
      case 'H' : hPosChannel = channelNo; break;
      case 'V' : vPosChannel = channelNo; break;
      default : break; // static channel, just set default once
    }
    // set initial default value (will stay in the buffer)
    setDMXChannel(channelNo, defaultValue);
  }
  // now create device according to type
  if (olaType==ola_dimmer) {
    // Single channel DMX512 dimmer, only use white channel
    // - is light
    primaryGroup = group_yellow_light;
    // - use light settings, which include a scene table
    installSettings(DeviceSettingsPtr(new LightDeviceSettings(*this)));
    // - add simple single-channel light behaviour
    LightBehaviourPtr l = LightBehaviourPtr(new LightBehaviour(*this));
    l->setHardwareOutputConfig(outputFunction_dimmer, outputmode_gradual, usage_undefined, false, -1);
    addBehaviour(l);
  }
  else if (olaType==ola_fullcolordimmer) {
    // - is RGB
    primaryGroup = group_yellow_light;
    if (redChannel!=dmxNone && greenChannel!=dmxNone && blueChannel!=dmxNone) {
      // Complete set of outputs to create RGB light
      if (hPosChannel!=dmxNone || vPosChannel!=dmxNone) {
        // also has position, use moving light behaviour
        installSettings(DeviceSettingsPtr(new MovingLightDeviceSettings(*this)));
        // - add moving color light behaviour
        MovingLightBehaviourPtr ml = MovingLightBehaviourPtr(new MovingLightBehaviour(*this));
        addBehaviour(ml);
      }
      else {
        // just color light settings, which include a color scene table
        installSettings(DeviceSettingsPtr(new ColorLightDeviceSettings(*this)));
        // - add multi-channel color light behaviour (which adds a number of auxiliary channels)
        RGBColorLightBehaviourPtr l = RGBColorLightBehaviourPtr(new RGBColorLightBehaviour(*this));
        addBehaviour(l);
      }
    }
  }
  deriveDsUid();
}
Exemple #7
0
void OlaDevice::applyChannelValueSteps(bool aForDimming, double aStepSize)
{
  // generic device, show changed channels
  if (olaType==ola_dimmer) {
    // single channel dimmer
    LightBehaviourPtr l = boost::dynamic_pointer_cast<LightBehaviour>(output);
    double w = l->brightnessForHardware()*255/100;
    setDMXChannel(whiteChannel,(DmxValue)w);
    // next step
    if (l->brightnessTransitionStep(aStepSize)) {
      ALOG(LOG_DEBUG, "transitional DMX512 value %d=%d", whiteChannel, (int)w);
      // not yet complete, schedule next step
      transitionTicket = MainLoop::currentMainLoop().executeOnce(
        boost::bind(&OlaDevice::applyChannelValueSteps, this, aForDimming, aStepSize),
        TRANSITION_STEP_TIME
      );
      return; // will be called later again
    }
    if (!aForDimming) {
      ALOG(LOG_INFO, "final DMX512 channel %d=%d", whiteChannel, (int)w);
    }
    l->brightnessApplied(); // confirm having applied the new brightness
  }
  else if (olaType==ola_fullcolordimmer) {
    // RGB, RGBW or RGBWA dimmer
    RGBColorLightBehaviourPtr cl = boost::dynamic_pointer_cast<RGBColorLightBehaviour>(output);
    MovingLightBehaviourPtr ml = boost::dynamic_pointer_cast<MovingLightBehaviour>(output);
    // RGB lamp, get components
    double r,g,b;
    double w = 0;
    double a = 0;
    if (whiteChannel!=dmxNone) {
      if (amberChannel!=dmxNone) {
        // RGBW
        cl->getRGBWA(r, g, b, w, a, 255);
        setDMXChannel(amberChannel,(DmxValue)a);
      }
      else {
        // RGBW
        cl->getRGBW(r, g, b, w, 255);
      }
      setDMXChannel(whiteChannel,(DmxValue)w);
    }
    else {
      // RGB
      cl->getRGB(r, g, b, 255); // get brightness per R,G,B channel
    }
    // There's always RGB
    setDMXChannel(redChannel,(DmxValue)r);
    setDMXChannel(greenChannel,(DmxValue)g);
    setDMXChannel(blueChannel,(DmxValue)b);
    // there might be position as well
    double h = 0;
    double v = 0;
    if (ml) {
      h = ml->horizontalPosition->getTransitionalValue()/100*255;
      setDMXChannel(hPosChannel,(DmxValue)h);
      v = ml->verticalPosition->getTransitionalValue()/100*255;
      setDMXChannel(vPosChannel,(DmxValue)v);
      // step position
      ml->positionTransitionStep(aStepSize);
    }
    // next step
    if (cl->colorTransitionStep(aStepSize)) {
      ALOG(LOG_DEBUG,
        "transitional DMX512 values R(%hd)=%d, G(%hd)=%d, B(%hd)=%d, W(%hd)=%d, A(%hd)=%d, H(%hd)=%d, V(%hd)=%d",
        redChannel, (int)r, greenChannel, (int)g, blueChannel, (int)b,
        whiteChannel, (int)w, amberChannel, (int)a,
        hPosChannel, (int)h, vPosChannel, (int)v
      );
      // not yet complete, schedule next step
      transitionTicket = MainLoop::currentMainLoop().executeOnce(
        boost::bind(&OlaDevice::applyChannelValueSteps, this, aForDimming, aStepSize),
        TRANSITION_STEP_TIME
      );
      return; // will be called later again
    }
    if (!aForDimming) {
      ALOG(LOG_INFO,
        "final DMX512 values R(%hd)=%d, G(%hd)=%d, B(%hd)=%d, W(%hd)=%d, A(%hd)=%d, H(%hd)=%d, V(%hd)=%d",
        redChannel, (int)r, greenChannel, (int)g, blueChannel, (int)b,
        whiteChannel, (int)w, amberChannel, (int)a,
        hPosChannel, (int)h, vPosChannel, (int)v
      );
    }
  }
}
DigitalIODevice::DigitalIODevice(StaticDeviceContainer *aClassContainerP, const string &aDeviceConfig) :
  StaticDevice((DeviceClassContainer *)aClassContainerP),
  digitalIoType(digitalio_unknown)
{
  // last : separates behaviour from pin specification
  size_t i = aDeviceConfig.rfind(":");
  string ioname = aDeviceConfig;
  bool inverted = false;
  if (i!=string::npos) {
    ioname = aDeviceConfig.substr(0,i);
    string mode = aDeviceConfig.substr(i+1,string::npos);
    if (mode[0]=='!') {
      inverted = true;
      mode.erase(0,1);
    }
    if (mode=="button")
      digitalIoType = digitalio_button;
    else if (mode=="input")
      digitalIoType = digitalio_input;
    else if (mode=="light")
      digitalIoType = digitalio_light;
    else if (mode=="relay") {
      digitalIoType = digitalio_relay;
    }
    else {
      LOG(LOG_ERR,"unknown digital IO type: %s\n", mode.c_str());
    }
  }
  // basically act as black device so we can configure colors
  if (digitalIoType==digitalio_button) {
    primaryGroup = group_black_joker;
    // Standard device settings without scene table
    installSettings();
    // Digital input as button
    buttonInput = ButtonInputPtr(new ButtonInput(ioname.c_str(), inverted));
    buttonInput->setButtonHandler(boost::bind(&DigitalIODevice::buttonHandler, this, _1, _2), true);
    // - create one button input
    ButtonBehaviourPtr b = ButtonBehaviourPtr(new ButtonBehaviour(*this));
    b->setHardwareButtonConfig(0, buttonType_undefined, buttonElement_center, false, 0, false); // mode not restricted
    b->setGroup(group_yellow_light); // pre-configure for light
    addBehaviour(b);
  }
  else if (digitalIoType==digitalio_input) {
    primaryGroup = group_black_joker;
    // Standard device settings without scene table
    installSettings();
    // Digital input as binary input (AKM, automation block type)
    buttonInput = ButtonInputPtr(new ButtonInput(ioname.c_str(), inverted));
    buttonInput->setButtonHandler(boost::bind(&DigitalIODevice::inputHandler, this, _1, _2), true);
    // - create one binary input
    BinaryInputBehaviourPtr b = BinaryInputBehaviourPtr(new BinaryInputBehaviour(*this));
    b->setHardwareInputConfig(binInpType_none, usage_undefined, true, Never);
    addBehaviour(b);
  }
  else if (digitalIoType==digitalio_light) {
    // Digital output as light on/off switch
    primaryGroup = group_yellow_light;
    indicatorOutput = IndicatorOutputPtr(new IndicatorOutput(ioname.c_str(), inverted, false));
    // - use light settings, which include a scene table
    installSettings(DeviceSettingsPtr(new LightDeviceSettings(*this)));
    // - add simple single-channel light behaviour
    LightBehaviourPtr l = LightBehaviourPtr(new LightBehaviour(*this));
    l->setHardwareOutputConfig(outputFunction_switch, usage_undefined, false, -1);
    addBehaviour(l);
  }
  else if (digitalIoType==digitalio_relay) {
    primaryGroup = group_black_joker;
    // - standard device settings with scene table
    installSettings(DeviceSettingsPtr(new SceneDeviceSettings(*this)));
    // Digital output
    indicatorOutput = IndicatorOutputPtr(new IndicatorOutput(ioname.c_str(), inverted, false));
    // - add generic output behaviour
    OutputBehaviourPtr o = OutputBehaviourPtr(new OutputBehaviour(*this));
    o->setHardwareOutputConfig(outputFunction_switch, usage_undefined, false, -1);
    o->setGroupMembership(group_black_joker, true); // put into joker group by default
    o->addChannel(ChannelBehaviourPtr(new DigitalChannel(*o)));
    addBehaviour(o);
  }
	deriveDsUid();
}
Exemple #9
0
EnoceanDevicePtr EnoceanRemoteControlHandler::newDevice(
  EnoceanDeviceContainer *aClassContainerP,
  EnoceanAddress aAddress,
  EnoceanSubDevice &aSubDeviceIndex,
  EnoceanProfile aEEProfile, EnoceanManufacturer aEEManufacturer,
  bool aNeedsTeachInResponse
) {
  EnoceanDevicePtr newDev; // none so far
  if (EEP_RORG(aEEProfile)==PSEUDO_RORG_REMOTECONTROL) {
    // is a remote control device
    if (EEP_FUNC(aEEProfile)==PSEUDO_FUNC_SWITCHCONTROL && aSubDeviceIndex<1) {
      // device using F6 RPS messages to control actors
      if (EEP_TYPE(aEEProfile)==PSEUDO_TYPE_ON_OFF) {
        // simple on/off relay device
        newDev = EnoceanDevicePtr(new EnoceanRelayControlDevice(aClassContainerP));
        // standard single-value scene table (SimpleScene)
        newDev->installSettings(DeviceSettingsPtr(new SceneDeviceSettings(*newDev)));
        // assign channel and address
        newDev->setAddressingInfo(aAddress, aSubDeviceIndex);
        // assign EPP information
        newDev->setEEPInfo(aEEProfile, aEEManufacturer);
        // is joker
        newDev->setPrimaryGroup(group_black_joker);
        // function
        newDev->setFunctionDesc("on/off relay");
        // is always updateable (no need to wait for incoming data)
        newDev->setAlwaysUpdateable();
        // - add standard output behaviour
        OutputBehaviourPtr o = OutputBehaviourPtr(new OutputBehaviour(*newDev.get()));
        o->setHardwareOutputConfig(outputFunction_switch, outputmode_binary, usage_undefined, false, -1);
        o->setGroupMembership(group_black_joker, true); // put into joker group by default
        o->addChannel(ChannelBehaviourPtr(new DigitalChannel(*o)));
        // does not need a channel handler at all, just add behaviour
        newDev->addBehaviour(o);
        // count it
        aSubDeviceIndex++;
      }
      else if (EEP_TYPE(aEEProfile)==PSEUDO_TYPE_SWITCHED_LIGHT) {
        // simple on/off relay device
        newDev = EnoceanDevicePtr(new EnoceanRelayControlDevice(aClassContainerP));
        // light device scene
        newDev->installSettings(DeviceSettingsPtr(new LightDeviceSettings(*newDev)));
        // assign channel and address
        newDev->setAddressingInfo(aAddress, aSubDeviceIndex);
        // assign EPP information
        newDev->setEEPInfo(aEEProfile, aEEManufacturer);
        // is light
        newDev->setPrimaryGroup(group_yellow_light);
        // function
        newDev->setFunctionDesc("on/off light");
        // is always updateable (no need to wait for incoming data)
        newDev->setAlwaysUpdateable();
        // - add standard output behaviour
        LightBehaviourPtr l = LightBehaviourPtr(new LightBehaviour(*newDev.get()));
        l->setHardwareOutputConfig(outputFunction_switch, outputmode_binary, usage_undefined, false, -1);
        // does not need a channel handler at all, just add behaviour
        newDev->addBehaviour(l);
        // count it
        aSubDeviceIndex++;
      }
      else if (EEP_TYPE(aEEProfile)==PSEUDO_TYPE_BLIND) {
        // full-featured blind controller
        newDev = EnoceanDevicePtr(new EnoceanBlindControlDevice(aClassContainerP));
        // standard single-value scene table (SimpleScene) with Shadow defaults
        newDev->installSettings(DeviceSettingsPtr(new ShadowDeviceSettings(*newDev)));
        // assign channel and address
        newDev->setAddressingInfo(aAddress, aSubDeviceIndex);
        // assign EPP information
        newDev->setEEPInfo(aEEProfile, aEEManufacturer);
        // is shadow
        newDev->setPrimaryGroup(group_grey_shadow);
        // function
        newDev->setFunctionDesc("blind control");
        // is always updateable (no need to wait for incoming data)
        newDev->setAlwaysUpdateable();
        // - add shadow behaviour
        ShadowBehaviourPtr sb = ShadowBehaviourPtr(new ShadowBehaviour(*newDev.get()));
        sb->setHardwareOutputConfig(outputFunction_positional, outputmode_gradual, usage_undefined, false, -1);
        sb->setHardwareName("blind");
        sb->setDeviceParams(shadowdevice_jalousie, false, MIN_MOVE_TIME, MAX_SHORT_MOVE_TIME, MIN_LONG_MOVE_TIME);
        sb->position->syncChannelValue(100); // assume fully up at beginning
        sb->angle->syncChannelValue(100); // assume fully open at beginning
        // does not need a channel handler at all, just add behaviour
        newDev->addBehaviour(sb);
        // count it
        aSubDeviceIndex++;
      }
    }
  }
  // remote control devices never need a teach-in response
  // return device (or empty if none created)
  return newDev;
}
Exemple #10
0
AnalogIODevice::AnalogIODevice(StaticVdc *aVdcP, const string &aDeviceConfig) :
  StaticDevice((Vdc *)aVdcP),
  analogIOType(analogio_unknown),
  timerTicket(0),
  scale(1),
  offset(0)
{
  // Config is:
  //  <pin(s) specification>:[<behaviour mode>]
  //  - where ! before the behaviour mode means inverted operation (in addition to possibly inverted pin specs)
  //  - where pin specification describes the actual I/Os to be used (see DigitialIO)
  string ioname = aDeviceConfig;
  string mode = "dimmer"; // default to dimmer
  size_t i = aDeviceConfig.find(":");
  if (i!=string::npos) {
    ioname = aDeviceConfig.substr(0,i);
    mode = aDeviceConfig.substr(i+1,string::npos);
  }
  if (mode=="dimmer")
    analogIOType = analogio_dimmer;
  else if (mode=="rgbdimmer")
    analogIOType = analogio_rgbdimmer;
  else if (mode=="valve")
    analogIOType = analogio_valve;
  else if (mode.find("sensor")==0) // sensor can have further specification in mode string
    analogIOType = analogio_sensor;
  else {
    LOG(LOG_ERR, "unknown analog IO type: %s", mode.c_str());
  }
  // by default, act as black device so we can configure colors
  colorClass = class_black_joker;
  if (analogIOType==analogio_dimmer) {
    // Analog output as dimmer
    analogIO = AnalogIoPtr(new AnalogIo(ioname.c_str(), true, 0));
    // - is light
    colorClass = class_yellow_light;
    // - use light settings, which include a scene table
    installSettings(DeviceSettingsPtr(new LightDeviceSettings(*this)));
    // - add simple single-channel light behaviour
    LightBehaviourPtr l = LightBehaviourPtr(new LightBehaviour(*this));
    l->setHardwareOutputConfig(outputFunction_dimmer, outputmode_gradual, usage_undefined, false, -1);
    addBehaviour(l);
  }
  else if (analogIOType==analogio_rgbdimmer) {
    // - is light
    colorClass = class_yellow_light;
    // - need 3 IO names for R,G,B, optional fourth for W
    size_t p;
    p = ioname.find("|");
    if (p!=string::npos) {
      // at least 2 pins specified
      // - create red output
      analogIO = AnalogIoPtr(new AnalogIo(ioname.substr(0,p).c_str(), true, 0));
      ioname.erase(0,p+1);
      p = ioname.find("|");
      if (p!=string::npos) {
        // 3 pins specified
        // - create green output
        analogIO2 = AnalogIoPtr(new AnalogIo(ioname.substr(0,p).c_str(), true, 0));
        ioname.erase(0,p+1);
        p = ioname.find("|");
        if (p!=string::npos) {
          // extra 4th pin for white specified
          // - create white output from rest
          analogIO4 = AnalogIoPtr(new AnalogIo(ioname.substr(p+1).c_str(), true, 0));
          ioname.erase(p); // remove specification of white channel
        }
        // - create blue output from rest
        analogIO3 = AnalogIoPtr(new AnalogIo(ioname.c_str(), true, 0));
        // Complete set of outputs, now create RGB light (with optional white channel)
        // - use color light settings, which include a color scene table
        installSettings(DeviceSettingsPtr(new ColorLightDeviceSettings(*this)));
        // - add multi-channel color light behaviour (which adds a number of auxiliary channels)
        RGBColorLightBehaviourPtr l = RGBColorLightBehaviourPtr(new RGBColorLightBehaviour(*this, false));
        addBehaviour(l);
      }
    }
  }
  else if (analogIOType==analogio_valve) {
    // Analog output as valve controlling output
    analogIO = AnalogIoPtr(new AnalogIo(ioname.c_str(), true, 0));
    // - is heating
    colorClass = class_blue_climate;
    // - valve needs climate control scene table (ClimateControlScene)
    installSettings(DeviceSettingsPtr(new ClimateDeviceSettings(*this)));
    // - create climate control outout
    OutputBehaviourPtr ob = OutputBehaviourPtr(new ClimateControlBehaviour(*this, climatedevice_simple, hscapability_heatingAndCooling));
    ob->setGroupMembership(group_roomtemperature_control, true); // put into room temperature control group by default, NOT into standard blue)
    ob->setHardwareOutputConfig(outputFunction_positional, outputmode_gradual, usage_room, false, 0);
    ob->setHardwareName("Valve, 0..100");
    addBehaviour(ob);
  }
  else if (analogIOType==analogio_sensor) {
    int sensorType = sensorType_none;
    int sensorUsage = usage_undefined;
    double min = 0;
    double max = 100;
    double resolution = 1;
    int pollIntervalS = 30;
    scale = 1;
    offset = 0;
    // optionally, sensor can specify type, usage, sensor;tt;uu;mi;ma;res
    sscanf(mode.c_str(), "sensor;%d;%d;%d;%lf;%lf", &sensorType, &sensorUsage, &pollIntervalS, &scale, &offset);
    // Analog input as sensor
    analogIO = AnalogIoPtr(new AnalogIo(ioname.c_str(), false, 0));
    // - query native range
    analogIO->getRange(min, max, resolution);
    min = min*scale+offset;
    max = max*scale+offset;
    resolution = resolution*scale;
    // sensor only, standard settings without scene table
    installSettings();
    // single sensor behaviour
    SensorBehaviourPtr sb = SensorBehaviourPtr(new SensorBehaviour(*this, "")); // automatic
    sb->setHardwareSensorConfig((VdcSensorType)sensorType, (VdcUsageHint)sensorUsage, min, max, resolution, pollIntervalS*Second, pollIntervalS*Second);
    addBehaviour(sb);
    // install polling for it
    timerTicket = MainLoop::currentMainLoop().executeOnce(boost::bind(&AnalogIODevice::analogInputPoll, this, _1, _2));
  }
	deriveDsUid();
}
Exemple #11
0
void AnalogIODevice::applyChannelValueSteps(bool aForDimming, double aStepSize)
{
  // generic device, show changed channels
  if (analogIOType==analogio_dimmer) {
    // single channel PWM dimmer
    LightBehaviourPtr l = boost::dynamic_pointer_cast<LightBehaviour>(output);
    bool moreSteps = l->brightnessTransitionStep(aStepSize);
    double w = l->brightnessForHardware();
    double pwm = l->brightnessToPWM(w, 100);
    analogIO->setValue(pwm);
    // next step
    if (moreSteps) {
      ALOG(LOG_DEBUG, "AnalogIO transitional brightness value: %.2f", w);
      // not yet complete, schedule next step
      timerTicket = MainLoop::currentMainLoop().executeOnce(
        boost::bind(&AnalogIODevice::applyChannelValueSteps, this, aForDimming, aStepSize),
        TRANSITION_STEP_TIME
      );
      return; // will be called later again
    }
    if (!aForDimming) ALOG(LOG_INFO, "AnalogIO final PWM value: %.2f", w);
  }
  else if (analogIOType==analogio_rgbdimmer) {
    // three channel RGB PWM dimmer
    RGBColorLightBehaviourPtr cl = boost::dynamic_pointer_cast<RGBColorLightBehaviour>(output);
    bool moreSteps = cl->brightnessTransitionStep(aStepSize);
    if (cl->colorTransitionStep(aStepSize)) moreSteps = true;
    // RGB lamp, get components
    double r, g, b, pwm;
    double w = 0;
    if (analogIO4) {
      // RGBW lamp
      cl->getRGBW(r, g, b, w, 100); // get brightness for R,G,B,W channels
      pwm = cl->brightnessToPWM(w, 100);
      analogIO4->setValue(pwm);
    }
    else {
      // RGB only
      cl->getRGB(r, g, b, 100); // get brightness for R,G,B channels
    }
    // - red
    pwm = cl->brightnessToPWM(r, 100);
    analogIO->setValue(pwm);
    // - green
    pwm = cl->brightnessToPWM(g, 100);
    analogIO2->setValue(pwm);
    // - blue
    pwm = cl->brightnessToPWM(b, 100);
    analogIO3->setValue(pwm);
    // next step
    if (moreSteps) {
      ALOG(LOG_DEBUG, "AnalogIO transitional RGBW values: R=%.2f G=%.2f, B=%.2f, W=%.2f", r, g, b, w);
      // not yet complete, schedule next step
      timerTicket = MainLoop::currentMainLoop().executeOnce(
        boost::bind(&AnalogIODevice::applyChannelValueSteps, this, aForDimming, aStepSize),
        TRANSITION_STEP_TIME
      );
      return; // will be called later again
    }
    if (!aForDimming) ALOG(LOG_INFO, "AnalogIO final RGBW values: R=%.2f G=%.2f, B=%.2f, W=%.2f", r, g, b, w);
  }
}