since #13801, it's not been possible to add new milight things,
because the thing XML already has the new channel types, but not
the thingTypeVersion property set, so it would try to apply the
update instructions and error about duplicate channels
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.espmilighthub] use system channel types for color temp and brightness
closes#10096
also add absolute color temp channel. and remove level channel when we
already have a color channel (you can link a DimmerItem to a color
channel if your light doesn't happen to have color or you want direct
control of brightness only for some reason)
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] add support for Update component
This component is fairly non-standard - it doesn't add any channels.
Instead, it provides several properties to the thing, and also adds
a thing configuration allowing you to trigger an OTA update on a
Home Assistant device from MainUI.
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] improve Cover support
* Add support for covers that report position
* Handle when command and state values for OPEN/CLOSE/STOP
differ (as they do by default)
* Expose the full cover state, since it can have tell you
if the cover is moving or not
* Handle covers that have a position only, but not a state
* add constants to clarify up/down values
* Be sure to parse percents from strings in RollshutterValue
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt] Interpet incoming NaN as UNDEF for NumberValues
Since DecimalType and QuantityType don't support NaN, but
when you're linking to a topic that the device is using
floating point, NaN might happen.
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] interpret a dimmable light as OFF properly from zigbee2mqtt
zigbee2mqtt can send a brightness of say 99, with a state of OFF, when a bulb is
off. make sure if state is sent, it overrides all other inferences
* handle brightness but not color bulbs
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
I.e. Button, Scene, and Binary Sensors.
Also ensure we set up the CommandDescription, since some value types mights use it.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] Add support for Button component
* use a StringValue instead of an OnOffValue
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
Follow on to #15427
ring-mqtt sends `"name": ""`, not `"name": null` or simply omitting it,
so be sure to handle that way as well
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] handle null component name
channels from such components will not have a group. this is
now done by zigbee2mqtt for the "default" component of a device,
such as the light. HASS encourages this as of release 2023.8
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] support color temp on JSON schema lights
also adds a color_mode channel if color temp is possible, so you can
know how the bulb is behaving
* put color mode channel construction into buildChannels()
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
the min/max from the config are specifically only for the set point.
i.e. for a heater in winter when the heater is off, it may have
a set point range of 65-104°F, but if it's off for an unoccopied room
the ambient temperature might drop far below 65
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] implement JSON schema lights
* [mqtt.homeassistant] use enum for current state of color mode
* [mqtt.homeassistant] use implicit lambdas
* [mqtt.homeassistant] remove string constants in favor of an enum
* [mqtt.homeassistant] allow sending ON and brightness commands through bare
* [mqtt.homeassistant] turn down debug logging
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] unify all enum handling
regardless of if it's a required or optional characteristic,
or even "boolean" enums
then allow number or switch items to be linked with enums
then update the docs listing the numeric value for enums
as part of this, global configuration of thermostat enum values
is no longer supported; you must use metadata.
in particular, for GarageDoorOpener, the global settings didn't
even actually work, so they should work now.
Fixes#13595
* [homekit] default-invert boolean items for garage door states
this was previously handled explicitly by the switch statement.
so need to set the inverted flag now that we're building a
mapping instead
* [homekit] document that CurrentDoorState can be linked to a Contact item
* [homekit] improve docs on invert param to createMapping
also fix a new helper method not properly passing through the inverted
param
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.generic] separate command parsing from cached value updating
fixes#12150
Previously, Value.update would parse the command, _and_ update the cached
value with that command. Which means that when sending a command towards
MQTT (instead of processing an update from MQTT), the cached value was
unintentionally updated. This prevented the REFRESH command from returning
the most recent value received from the device.
Separating the two concerns also makes the test more obvious what they are
testing, and vastly simplified a kludgy workaround that RollershutterValue
was using to be able to process Commands that aren't States.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.generic] split Value::parseCommand into parseMessage
so that a particular value type subclass can have varying implementations
if it desires
---------
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [jrubyscripting] allow disabling dependency tracking
in case your helper library doesn't support it. or you just don't like
the behavior.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] support command_template for fan components
* [mqtt.homeassistant] fix field declaration for consistency
Signed-off-by: Cody Cutrer <cody@cutrer.us>
openHAB doesn't have the concept of "enabled by default", since _everything_
is technically "disabled" until you link it to an item. It seems devices
use disabled by default on less common entities, such as zigbee2mqtt
marking a binary_sensor as a "backup" method to an update entity for
when an update is available, or a sensor as a "backup" method to a
select entity. So in that case, just hiding these channels unless the user
clicks "Show Advanced" seems to map best.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] Implement IrrigationSystem
Fairly trivial now, except that a ServiceLabelService has to be added
to the accessory.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] TV accessory
Now possible since we support multiple secondary services. Just need to explicitly
declare that InputSource is a linked service to a Television, not just a secondary
service.
Note also that since TV and related services have so many mandatary characteristics
that are often static, I introduced a new way to declare characteristics -
via metadata on the service's item. Honestly, I feel like it's a lot cleaner to
have a factory create the mandatory characteristics the same way as the optional
characteristics, and then construct the service ourselves instead of basing the
service on the specific accessory interface. But this commit is already big enough,
I didn't want to go refactoring _all_ of the accessories to do it that way just
yet. This is why I have "unused" metadata characteristic factory methods for
AirQuality, HeaterCooler, and Thermostat - I started to make those configurable
via metadata, then realized they were mandatory characteristics that couldn't
be found from metadata via the current infrastructure.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] improve instance management
* allow addressing individual instances for most console commands
* don't restart all instances if simply adding/removing instances on
config change
* clear stored info when removing instances
* [homekit] reset instance identity when clearing pairings
* [homekit] log the actual interface we looked up
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] support Rollershutter items for HoldPosition
just send STOP to them
* [homekit] log a warning for incompatible HoldPosition items
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] allow configuring secondary services as members of a group
Required introduction of AccessoryGroup to represent the base
AccessoryInformationService for ease of configuring multiple of the
same service.
This is also "breaking" in that someone who previously had HomeKit
accessories nested directly inside of a group that was itself a
HomeKit accessory will now have those items grouped within the Home
app.
* [homekit] combine multiple readme sections on complex accessories
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] delay starting until a particular StartLevel
instead of a blind "delay by seconds", the new default won't even
attempt to start until items are loaded (both file-based and UI-based),
with an additional config to let the user delay it any further (in
case they have items coming from JSR223 scripts that can't run until
at least SL20 anyway).
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] add BasicFan accessory
This is Fan v1. It's a subset of FanV2, except that Home allows you
to customize the icon to show a ceiling fan.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
just the sub-commands.
since the show command is already a "search", I didn't feel it's super
important to implement on that
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] persist all known accessories, to prevent loss of homekit information
See the readme for more details, but basically this keeps track of every
accessory we've ever created, and if it no longer exists, presents a dummy
accessory instead. If the accessory comes back, nothing is lost in the Home
app; if you meant to prune it permanently, you have to run a console command.
there are also several fixes to prevent presenting the device with missing data -
such as when the bundle stops, _don't_ explicitly remove the accessories until
the server has stopped.
we also don't increment the configuration version unless the configuration
has _actually_ changed (so removing and re-adding the exact same thing
won't trigger the device to reconnect). this even works across restarts
of the bundle, because we're persisting all the accessory information
for dummy information anyway.
* [homekit] Address review comments for accessory persistence
* update hap-java to 2.0.4
* remove unused local variable
* [homekit] ensure accessories are replaced in a batch
so that HAP-Java can maintain subscriptions with the new objects
* [homekit] log individual dummy accessories up to 5
* [homekit] Tweak readme for dummy accessories slightly.
* Be consistent with proper usage of useDummyAccessories.
* Make the sentence more clear about the effects of having dummy accessories.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* First commit on newly created branch, taking code from c8b8e210dfd23f98526763782eadbca49509baf9
* [bondhome] update snapshot version, and some typos
* [bondhome] Address (most) comments from prior review from #7260
* [bondhome] simplify channels
* lastUpdate is unnecessary; turn on persistence or add a rule on update if
you care to keep track of it
* use a single string command channel for all shoot-and-forget commands, instead
of multiple switch channels
* use a rollershutter channel for shades (accepting UP, DOWN, STOP, 0%, and 100%)
* on all dimmer channels, accept ON and OFF, as well as 0% to imply OFF, instead
of having to write rules to control ON/OFF state separately.
* if the dimmer channel exists, prune the corresponding power channel, since
the dimmer channel is now a pure superset of its functionality
* overload fan#speed to be ceiling fan or a fireplace's fan, depending on the
device type
* [bondhome] add bundle to the BOM pom
* [bondhome] clean up BondDeviceHandler a bit
* there's no need to delay initialization; ThingManager won't
even attempt to initialize a child thing until its bridge is online
* Remove some extra initialization checks that can never be false
* slightly refactor some methods to return early, rather than
nest a giant `else`
* remove some info logging that will get triggered in normal usage
* [bondhome] fix bridge discovery
* Bridge property and config serial number need to be the same name
* Don't arbitrarily delay the BPUPListener
* Automatically update the IP if the BPUPListener finds it
* Provide the new bridge with its discovered IP to avoid an additional
DNS query
* Don't get the bridge version after every keep-alive response
* [bondhome] trigger end-device discovery as soon as the bridge comes online
* [bondhome] remove internal binding version
* [bondhome] change addr property to string
Certain values seen in the wild when interpreted as a long are too big for that
storage. Also, the Bond API documentation describes the addr property on a
device to be a string.
OpenHAB already has infrastructure to have things update their
channel definitions when a binding is updated.
* [bondhome] ignore any device that starts with _
In v3 of their API, Bond added a new special entry of __. Because no valid
device id would start with an underscore, ignore everything that starts with an
underscore to fix v3 and maybe futureproof.
* address review comments
mostly adding i18n to error states, and cleaning up error handling of
HTTP requests.
* use builtin translation services
instead of plumbing our own provider through
* use System.nanoTime instead of currentTimeMillis
so that it will be a monotonic clock, not (as) susceptible to the clock
changing
* [bondhome] ignore BPUP messasges that aren't state
In recent firmware, bond is now sending action messages via BPUP as well as state.
This change ignores all messages that aren't state.
* [bondhome] Improve error handling, and remove dummy constants
Just use a single BondException class to communicate any sort of
error from within bond, and avoid throwing, catching, and re-throwing
the same (or slightly modified) exception.
Also remove dummy constants that might give the wrong impression
of the details of your Bond device. Then implement proper null checks,
especially setting a configuration error if key config properties
aren't set on the thing.
* [bondhome] avoid setting device status when bridge just went offline
* address static analysis tool problems
Also-by: Sara Damiano <sdamiano@stroudcenter.org>
Also-by: Keith T. Garner <kgarner@kgarner.com>
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [jrubyscripting] implement dependency tracking
watchers had to be refactored similar to jsscripting.
it supports watching any directory referenced from RUBYLIB,
as well as the gem home. it properly excludes lib and gem home
(as well as other gem homes if you have multiple jruby versions
installed) from loading as regular scripts.
this is a breaking change if you don't have RUBYLIB explicitly
configured, and you are using the old default directory.
it's expected that the detection of what files and gems any
given script uses will be self-identified by the script, presumably
by the helper library.
JRubyScriptEngineConfiguration was largely refactored as part of this.
* CONFIGURATION_PARAMETERS was renamed, and is no longer static, since
it's modified every time the configuration is changed
* OptionalConfigurationElement was simplified since default values
are always provided now. this also simplified lots of other code
that accesses the current settings.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.espmilight] Automatically convert color values to color temp for RGB+CCT bulbs
Yes, it's lots of math, but references are provided. This supplants
whiteThreshold for RGB+CCT bulbs since it is far more flexible and
accurate.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
otherwise if your step is 1.0 in fahrenheit, then your
values will get rounded to 1.0 celsius, and you might not
even notice you've lost precision in the Home app.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [mqtt.homeassistant] support non-RGB lights
dynamically decide which type of channel to expose. also send "down-typed"
commands to the proper topic. this also sets the groundwork for supporting
template and JSON schemas
Signed-off-by: Cody Cutrer <cody@cutrer.us>
So that other pieces of openhab can know what unit it's going to be,
without it having a value yet. Importantly, any necessary conversion
that need to be applied to the other portion of the state description -
min, max, and step.
See also https://github.com/openhab/openhab-core/pull/3132
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] increase flexibility of ColorTemperature
allow Number or Dimmer items, and mired or Kelvin units.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] Improve output of console's `homekit show` command
* include the full JSON from all the characteristics, so you can confirm
everything is configured correctly.
* only use simple class names; the fully qualified package is just a
distraction.
* show linked services if they exist
* include the class name of services, not just the GUID
Signed-off-by: Cody Cutrer <cody@cutrer.us>
If you have many instances, it can take a while. So stop all the
instances in parallel. Also, fix a race condition where the update
debouncer might get called again after being stopped, because the
change listener was deregistered _after_ the debouncer was stopped.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] fix BooleanItemReader to work with DimmerItems
DimmerItems have a PercentType state, which is easily convertible
to OnOffType, but is not inherited from it. So take that into account.
i.e. a variable speed fan can use a single DimmerItem for both
ActiveStatus and RotationSpeed.
* [homekit] Document that Dimmer is a possible item type for several booleans
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [homekit] allow configuring maxValue on VOCDensity
the default of 1000 is quite low in reality. tested and confirmed
working with iOS 16
* [homekit] allow step value to be configured for VOCDensity
Signed-off-by: Cody Cutrer <cody@cutrer.us>
this helps to auto-configure if the binding is providing the necessary info
metadata config still overrides
Signed-off-by: Cody Cutrer <cody@cutrer.us>
HASS registers availability topics before calling start(), so
the AbstractMQTTThingHandler was never subscribing/starting the
availability channel(s). So do so in start() of the base class.
I checked other implementations, and either they already handle
re-registering availabilityTopics in their start()
(GenericMQTTThingHandler), or they don't use availabilityTopics
at all from the base class and manage it themselves (Homie).
Note that this shows up as newly-added HASS things not having
a problem (because the components aren't discovered until after
the ThingHandler is started), but if you restart OpenHAB or
disable/enable the thing, the channels (and components) are
cached, thus how availabilityTopics are known before starting.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
pass the actual class objects through, and post-process in Ruby, to
avoid the rescue nil -- and by extension, any issues with visibility
into private objects from JRuby.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
Range is 0..255, not 0..250.
rgb -> hsv -> rgb still isn't perfect, but it's better. In
particular, I found this when using HSBType.BLUE in a test,
and it was coming out as 0,0,250 in RGB. It now comes out as
a proper 0,0,255.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
this is a theme, and I've extracted a helper method and applied it to several
other locations as well
example, I have a double-sliding door, with two contact sensors
in the alarm system, defined as:
```
Group:Contact:AND(CLOSED,OPEN) DeckDoor_Contact "Deck Door [%s]" <door> (gExteriorDoors, gWarningVisibility_Contact, gDoor, lMainFloor, gInflux) { homekit="ContactSensor" [instance=2] }
Contact DeckNDoor_Contact "Deck Door North" <door> (gInflux, DeckDoor_Contact, gGreatContacts) { channel="dscalarm:zone:46c52f35:zone11:zone_status" }
Switch DeckNDoor_Tamper "Deck Door North Tamper [%s]" <warning> (gTamper, gWarningVisibility_Switch) { channel="dscalarm:zone:46c52f35:zone11:zone_tamper" }
Contact DeckSDoor_Contact "Deck Door South" <door> (gInflux, DeckDoor_Contact, gGreatContacts) { channel="dscalarm:zone:46c52f35:zone12:zone_status" }
Switch DeckSDoor_Tamper "Deck Door South Tamper [%s]" <warning> (gTamper, gWarningVisibility_Switch) { channel="dscalarm:zone:46c52f35:zone12:zone_tamper" }
```
This allows the Group:Contact to be used for the ContactSensor.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
see reference in code comment, but a measurement sensor is assumed to
be numeric, even if it doesn't have a unit
Signed-off-by: Cody Cutrer <cody@cutrer.us>
given:
```
Group eThermostat { homekit="Thermostat" }
Number:Temperature Thermostat_AmbTemp (eThermostat) { homekit="CurrentTemperature" }
Number:Temperature Thermostat_SetTemp (eThermostat) { homekit="TargetTemperature" }
Group gThermostatZoneContacts
// in reality there are multiple thermostats and multiple of these groups,
// so that a rule on members of gThermostatZoneContacts can find the related
// thermostat to turn it off when a window is open
Group:Contact:OR(OPEN,CLOSED) gWindows (eThermostat, gThermostatZoneContacts)
Contact Window_Contact (gWindows) { homekit="ContactSensor" }
```
When constructing the Thermostat accessory for eThermostat, detects the
Window_Contact as a mandatory characteristic, because it's a base accessory
in a nested group. This leads to lots of warnings about the temperature
value of a contact item being out of range.
The fix is two-fold - first of all, there's no reason to search nested
groups for characteristics of a complex accessory. Second of all,
even if for some reason you were to nest an accessory in an accessory,
the nested accessory does not actually belong to the outer accessory,
so don't add it as a mandatory characteristic of the outer.
I suspect there's still one more bug, because AbstractHomekitAccessoryImpl.
getCharacteristic(HomekitCharacteristicType.CURRENT_TEMPERATURE) was
returning Window_Contact, which is only tagged as a ContactSensor. But
after fixing the above two bugs, it was no longer reproducible, and I
didn't continue digging.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
* [jrubyscripting] check if gems are installed before installing them
this avoids unecessary downloads and overwrites, or even more importantly
errors if the GEM_HOME is not writable by the openhab user.
this also adds a configuration option for if you want to check for
updates every time configuration is applied (or openhab restarts). this
is useful if your OpenHAB system can't access the internet regularly.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
this is especially important if you use the same item for both
TargetTemperature and HeatingThresholdTemperature characteristics,
since the former was already doing unit conversion for min/max.
Signed-off-by: Cody Cutrer <cody@cutrer.us>
fixes#10711
technically this code is in mqtt.generic, but it's only used by Homie.
in particular, if an incoming string doesn't match an enum, this will now
just ignore the value instead of raising an exception to be caught somewhere inside
of Hive MQTT, and eventually timing out and logging that mandatory topics weren't
received, instead of logging a pointer to the actual problem. this makes it so that
if there's a homie $datatype openhab doesn't understand (like duration), it will be
able to get to the point of just choosing a string channel
also did some minor debug logging cleanup for mqtt:
* fixed a typo
* when logging homie device name from the thing handler, use the config deviceid,
since we likely don't have the attributes from MQTT yet
Signed-off-by: Cody Cutrer <cody@cutrer.us>
if an Item associated with a temperature characteristic has a QuantityType
(of dimension Temperature) as its state, regardless of current unit,
use that to convert to celsius instead of any other configuration.
Note that this is only for supply values to HomeKit; commands coming from
HomeKit will still send a DecimalType with units according to the HomeKit-wide
useFahrenheit configuration.
Signed-off-by: Cody Cutrer <cody@cutrer.us>