NetatmoDevice::NetatmoDevice(NetatmoVdc *aVdcP, INetatmoComm& aINetatmoComm, JsonObjectPtr aDeviceData, VdcUsageHint aUsageArea, const string& aBaseStationId) : inherited(aVdcP), usageArea(aUsageArea), baseStationId(aBaseStationId), isPresent(true), measurementAbsloluteTimestamp(chrono::system_clock::to_time_t(chrono::system_clock::now())) { setIdentificationData(aDeviceData); setColorClass(class_white_singledevices); installSettings(DeviceSettingsPtr(new NetatmoDeviceSettings(*this))); // - set a action output behaviour (no classic output properties and channels) OutputBehaviourPtr ab = OutputBehaviourPtr(new ActionOutputBehaviour(*this)); ab->setGroupMembership(group_undefined, true); addBehaviour(ab); cbConnection = aINetatmoComm.registerCallback([=](auto...params){ this->updateData(params...); }); }
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; }
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(); }
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(); }