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); }
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); }
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); }
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); }
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(); }
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(); }
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; }
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(); }
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); } }