Closed mrguessed closed 5 years ago
Determine what's clearing out the JSONDB during service shutdown, and prevent it from clearing the JSONDB entries.
@kaikreuzer Do you have any idea? Am I using the storage service API in a wrong way and is a "keep" flag necessary somewhere?
This is the DEBUG log from the shutdown sequence:
2019-01-14 13:00:07.468 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedBreakfast
2019-01-14 13:00:07.481 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedMaster
2019-01-14 13:00:07.493 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item KitchenCoffeeMachineStatus
2019-01-14 13:00:07.511 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedKitchenBlackout
2019-01-14 13:00:07.522 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedKitchenBlinds
2019-01-14 13:00:07.531 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item FamilyHarmony_dvd
2019-01-14 13:00:07.552 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedBlackout
2019-01-14 13:00:07.559 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedKitchen
2019-01-14 13:00:07.584 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedDining
2019-01-14 13:00:07.603 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedFamilyBlackout
2019-01-14 13:00:07.614 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedLiving
2019-01-14 13:00:07.621 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item KitchenIslandLightsStatus
2019-01-14 13:00:07.627 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedBlinds
2019-01-14 13:00:07.640 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item KitchenKettle
2019-01-14 13:00:07.643 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedDinner
2019-01-14 13:00:07.646 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item PowerHotWaterPumpStatus
2019-01-14 13:00:07.648 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item FamilyHarmony_tv
2019-01-14 13:00:07.652 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedGoodnight
2019-01-14 13:00:07.679 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedHolidaySwitch
2019-01-14 13:00:07.693 [DEBUG] [.io.hueemulation.internal.LightItems] - Remove item GManagedMediaLights
2019-01-14 13:00:07.817 [DEBUG] [org.openhab.io.hueemulation ] - ServiceEvent UNREGISTERING - {org.openhab.io.hueemulation.internal.HueEmulationService}={service.id=457, service.bundleid=260, service.scope=bundle, restrictToTagsWhiteLights=Lighting, component.name=org.openhab.io.hueemulation.internal.HueEmulationService, service.config.label=Hue Emulation, component.id=298, createNewUserOnEveryEndpoint=false, restrictToTagsSwitches=Switchable, restrictToTagsColorLights=ColorLighting, discoveryHttpPort=80, pairingTimeout=600, pairingEnabled=false, service.config.category=io, service.config.description.uri=io:hueemulation, service.pid=org.openhab.hueemulation} - org.openhab.io.hueemulation
2019-01-14 13:00:07.841 [DEBUG] [org.openhab.io.hueemulation ] - ServiceEvent UNREGISTERING - {javax.servlet.ServletContext}={osgi.web.version=2.4.0, osgi.web.contextpath=/, service.id=458, osgi.web.symbolicname=org.openhab.io.hueemulation, service.bundleid=260, service.scope=singleton, osgi.web.contextname=default} - org.openhab.io.hueemulation
2019-01-14 13:00:07.878 [DEBUG] [org.openhab.io.hueemulation ] - BundleEvent STOPPING - org.openhab.io.hueemulation
2019-01-14 13:00:07.879 [DEBUG] [org.openhab.io.hueemulation ] - ServiceEvent UNREGISTERING - {org.osgi.service.cm.ManagedService}={service.id=456, service.bundleid=260, service.scope=singleton} - org.openhab.io.hueemulation
2019-01-14 13:00:07.880 [DEBUG] [org.openhab.io.hueemulation ] - BundleEvent STOPPED - org.openhab.io.hueemulation
Those "Remove Item..." log entries, from removed()
in (LightItems.java), appear to be the ones that are clearing out the Storage Service that's used by the Hue Emulation.
I'm thinking it should call close() before shutdown gets a chance to remove all the items. I'm looking into how this might be accomplished.
Had anybody any success in this matter? I mean it is quite serious somehow. I'm myself unfortunately busy with other areas in OH
How about using Openhab's item name as Hue's uniqueId? As far as I know item name is immutable and unique, and according to HueHab documentation it is string. Alexa work pretty well with such ids
The original hue bridge uses numbers only that's why we have numbers as well. It is actually even better to save the hue number as item meta data and not separate from the item.
I didn't know that item object can store metadata within itself. But in that case we still have an issue - sequence should be handled. I wonder if item name hashcode hashcode is distributed well enough. After all the simplest and fastest solution is item name.
I do not have a Hue developers account. If anyone can verify if arbitrary names can be used and quote that part that'd be helpful. If they restrict it to numbers only though we still need the mapping.
My openhab plugin (PoC) works with Alexa using item names.
There no description for root element, but in example we have string ("1")
{
"1": {
"state": {
....
},
....
}
https://developers.meethue.com/develop/hue-api/lights-api/#get-all-lights
A bit of internals (can be threaded as argument to use associated numeric ids): "Yes, as Wim says it is not possible to change a light ID. What you mention will work though, as deleting a light and finding it again will result in it being assigned the next available light id, but this is of course a bit messy and strictly speaking not a change light ID. Hue Support - Steve" https://developers.meethue.com/forum/t/change-light-id/4167
Yes I know that it's not an array, but an associate map with stringed keys. But I guess some sloppy apps and hue API consumers out there are converting those keys to numbers, because the original Hue bridge will only ever have numbers. That's my concern.
I mean ideally the hue emulation also works with the original Hue app and all kind of 3rd party apps. And that's why I want the API doc to clearly say "all imaginable keys can be used, but we will use numbers for now" or so.
@davidgraeff yes I totally agree with you. The answer, depends on purpose of the Openhab Addon.
In my opinion HueEmulator should be good enough to support several popular devices\apps. 100% emulation is not necessary and unreal :(
But back to your proposition to attach hueId to metadata "It is actually even better to save the hue number as item meta data and not separate from the item." How you will achieve that, storing metainfo in tags?
How you will achieve that, storing metainfo in tags?
No. That's what you would have done in 2.3, I guess. But since OH 2.4 there is a meta-data system in place. This is already used by haBot and by the auto-update feature. It's like attaching configuration to an Item, but namespaced. And in this case we would claim the namespace "hueemulation".
Well, then it sounds like almost perfect solution. Could you please share the link to the doc or sources?
Okay, I think I see a way here. If the item metadata stores the hueemulation ID, and the addon only stores the next-id integer, then we can use a simple incrementing value, which will only be assigned to a candidate item if missing from its metadata.
The max value of this ID is...? The hue bridge is said to support 50, with some reports of more being accomplished. Not clear what the protocol spec says. If too small, then need to get more tricksy with doing things like zwave: increase until max, then reuse IDs previously vacated. I'm thinking a safe starting point for max is 255.
Yup. 255 sounds reasonable. From that point on we will still expose further items but add a big warning to the log file.
sorry being like a broken radio, but MAX_INT as safe as 255. Documentation refers to 50 devices, not the length or type of hueId. Imho, just go with MAX_INT or better with timestamp (no need to keep max value). If there will be problem it will be reported.
I think the old maximum came from the fact that the first hue bridge was an embedded system with a reserved memory area for storing lights. The second edition is now a linux based system with AFAIK 256 mb ram, more than enough to store hundreds of lights.
And zigbee allows 65536 devices in one single mesh.
I'm thinking it should call close() before shutdown gets a chance to remove all the items. I'm looking into how this might be accomplished.
Did you check the "close()" option? I think if this works you could do a hotfix and invest some more time in the meta solution afterwards. I by myself ran into the problem yesterday after rebooting my rasp after some updates. "Alexa Kitchen off" turned off my tv... well. Sad girlfriend watching Netflix.
Is it possible to overwrite the jsondb? So that i could back it up on my pc and overwrite it after a reboot of openhab.
I really appreciate your work guys. It is great to have such a feature without having to use the... let's say quite instable cloud-service.
@schniddsel There is no working solution yet, as no jsondb maintainer has commented so far. Let's try again:
@openhab/core-maintainers
I read the first comment that describes the problem twice but I still don't understand it. That's surely caused by the fact that I never used the alexa integration and hue emulation of openHAB.
@davidgraeff Can you give it a try to explain me the situation? Or perhaps another maintainer that used that stuff already could comment.
The person for the jsondb storage internals could be @cdjackson as he has written that implementation. But I assume it is not storage implementation dependent (but cannot judge without understanding the problem at all).
tl;dr
The hue emulation requires a storage. Before I refactored it, it used custom files, but those were not part of the OH backup system, so I switched to the json storage API.
And now the problem: The json storage resets its content after each start (not on shutdown though). And I really do not understand why, the API doc does not say that it auto-prunes itself or similar.
The json storage resets its content
What does it mean? Reset to which state? Does the storage service provides an empty storage after each restart?
Does the storage service provides an empty storage after each restart?
Yes exactly. And the underlying file is cleared.
If the service is restarted during runtime, it picks up all the stored information correctly.
Did you check the file content as long as openHAB is not running? So, are the wrong information in the file or is it not deserialized correctly?
Yes exactly. And the underlying file is cleared.
So, the file exists and it is empty (size = 0 bytes)?
So, the file exists and it is empty (size = 0 bytes)?
I need to double check, but afaik yes it's an empty file. Maybe I'm just using the service in the wrong way.
You could modify the put
method to get some more information.
E.g.
public @Nullable T put(String key, @Nullable T value) {
if (logger.isTraceEnabled()) {
logger.trace("put to storage: file: {}, key: {}, value: {}", file, key, value, new RuntimeException("trace stacktrace"));
}
...
I was afraid that core bundle debugging is required. I have not fired up an openhab-core development setup yet. The IDE situation is not stable enough, especially if you put core and addon bundles into the same workspace.
You do not need "core bundle debugging".
You just need to modify that bundle (e.g. using a simple text editor), compile on command line and use that JAR it in your launch configuration.
You could also build the modified bundle add use that in your Karaf based OH runtime.
Then you only need to set the log level and read the log after a start-shutdown-cycle.
So that's why my Alexa devices were horribly confused every time I restarted the service. This is further compounded by Amazon caching the results on their servers, which resulted in me having four or five duplicates and no way to tell which was the right one.
Is there anything which I can do to help resolve this?
I'll migrate the service to the new build system tomorrow. And at that point I'll swap our made up hue IDs with openHAB item names.
I will test that with my Echos here. If that doesn't work I'll use item meta data to store assigned IDs.
Either way, after that change is merged and snapshots are working again, the emulated hue devices have to be discovered once more :/ (aka breaking change)
Done in #5243
Expected Behavior
The MAP of Hue Id's <-> openHAB Item names should remain constant throughout the lifetime of the Hue Emulation service.
Any Hue Id allocated by the service should not be re-used for a different Item name, and must survive openHAB Process restarts.
Current Behavior
The Hue Emulation service stores the MAP of Hue Id's to openHAB Item names is kept in JSONDB.
Under Linux, this ends up as JSON Text in a file like:
with contents like:
Hue Id's within this file are allocated sequentially, by the Hue Emulation service, and the file is written out as new entries are discovered.
This file is also read at Hue service (and thus openHAB) startup.
Hue Id's collected in this file are (indirectly) advertised to the Amazon Alexa service, during it's "Discover Devices" command, in the form of Hue Emulation Service URL's to call to interact with the Item.
When openHAB is shutdown, this file is cleared out and the original MAP of Hue Id's is lost. Upon openHAB restart, the file/storage is again rebuilt from the current version of the Items in the system.
If the Item definitions are changed (eg.
Lighting
tags added/removed), then the rebuilt MAP will now be inconsistent with that advertised to the Amazon Alexa service during it's "Discover Devices" command.In my case, my Item declarations are in
.items
files, and I tag/add/remove items within these files.In my case, I have 22 Items using Hue Emulation service.
Possible Solution
Determine what's clearing out the JSONDB during service shutdown, and prevent it from clearing the JSONDB entries.
OR;
Determine if we can use the Item name, or a long-enough Hash of it, in the Alexa Service URL instead of allocating/maintaining an "id" (number)
Steps to Reproduce (for Bugs)
Given the 22 Items listed above, or even a small number defined in your system, make a backup copy of the JSONDB file
/var/lib/openhab2/jsondb/hue.emulation.lights.json
hue.emulation.lights.json-before.txtDisable the
Lighting
tag on one of the Items, eg by renamingLighting
toLightingDISABLED
. The Item should be somewhere in the middle of the list (the Hue ID's appear unpredictably sequenced)Observe that the JSONDB file from step 1 has changed, removing the Item from the MAP and leaving a hole (expected)
Shutdown openHAB
Observe that the JSONDB file from step 1 has been emptied out (unexpected) hue.emulation.lights.json-shutdown.txt
Startup openHAB
Observe that the JSONDB file from step 1 now has completely different
value
(Hue Id's) for some number of entries. hue.emulation.lights.json-after.txtIn my case, I disabled the Item
GManagedFamily
by changing it's tag toLightingDISABLED
, and the before/after diff of the MAP/JSON looks like:ie. the
GManagedHolidaySwitch
changed from HueID 21 to HueID 20 (previously GManagedFamily` and the other have moved up also.Context
When the MAP is out of sync with the Amazon Alexa's version of the MAP (from Discover Devices), the wrong device will be operated on by Alexa Voice commands.
eg. "Alexa Turn Kitchen on" might instead turn on the Kettle
Your Environment
Reference
Community discussion: https://community.openhab.org/t/hue-emulation-re-sequences-hueids-on-openhab-service-restart-causes-out-of-sync-with-alexa
@davidgraeff FYI