Skip to content

Commit 5d54bc9

Browse files
Restructure of HueObjects. (diyhue#1031)
* Update light_types.py * Update v2restapi.py * restructure HueObjects * change hueobject * move eventStream * change event to StreamEvent * add light scan to eventstream * Update discover.py * Update discover.py * eventsteam for bridge name change * Update Light.py * Update Light.py * Update Light.py * Update Light.py * Update Light.py * revert back to old
1 parent 5c3e7ff commit 5d54bc9

23 files changed

+2086
-1987
lines changed

BridgeEmulator/HueObjects/ApiUser.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from datetime import datetime, timezone
2+
3+
class ApiUser():
4+
def __init__(self, username, name, client_key, create_date=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S"), last_use_date=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S")):
5+
self.username = username
6+
self.name = name
7+
self.client_key = client_key
8+
self.create_date = create_date
9+
self.last_use_date = last_use_date
10+
11+
def getV1Api(self):
12+
return {"name": self.name, "create date": self.create_date, "last use date": self.last_use_date}
13+
14+
def save(self):
15+
return {"name": self.name, "client_key": self.client_key, "create_date": self.create_date, "last_use_date": self.last_use_date}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import uuid
2+
import logManager
3+
from HueObjects import genV2Uuid, StreamEvent
4+
from datetime import datetime, timezone
5+
6+
logging = logManager.logger.get_logger(__name__)
7+
8+
class BehaviorInstance():
9+
def __init__(self, data):
10+
self.id_v2 = data["id"] if "id" in data else genV2Uuid()
11+
self.id_v1 = self.id_v2 # used for config save
12+
self.name = data["metadata"]["name"] if "name" in data["metadata"] else None
13+
self.configuration = data["configuration"]
14+
self.enabled = data["enabled"] if "enabled" in data else False
15+
self.active = data["active"] if "active" in data else False
16+
self.script_id = data["script_id"] if "script_id" in data else ""
17+
18+
streamMessage = {"creationtime": datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"),
19+
"data": [self.getV2Api()],
20+
"id": str(uuid.uuid4()),
21+
"type": "add"
22+
}
23+
StreamEvent(streamMessage)
24+
25+
def __del__(self):
26+
streamMessage = {"creationtime": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
27+
"data": [{"id": self.id_v2, "type": "behavior_instance"}],
28+
"id": str(uuid.uuid4()),
29+
"type": "delete"
30+
}
31+
StreamEvent(streamMessage)
32+
logging.info(self.name + " behaviour instance was destroyed.")
33+
34+
def getV2Api(self):
35+
result = {"configuration": self.configuration,
36+
"dependees": [],
37+
"enabled": self.enabled,
38+
"active": self.active,
39+
"id": self.id_v2,
40+
"last_error": "",
41+
"metadata": {
42+
"name": "noname"
43+
},
44+
"script_id": self.script_id,
45+
"status": "running" if self.enabled else "disabled",
46+
"type": "behavior_instance"
47+
}
48+
49+
if self.name != None:
50+
result["metadata"]["name"] = self.name
51+
52+
for resource in self.configuration["where"]:
53+
result["dependees"].append({"level": "critical",
54+
"target": {
55+
"rid": resource[list(resource.keys())[0]]["rid"],
56+
"rtype": resource[list(resource.keys())[0]]["rtype"]
57+
},
58+
"type": "ResourceDependee"
59+
})
60+
61+
return result
62+
63+
def update_attr(self, newdata):
64+
for key, value in newdata.items():
65+
if key == "metadata" and "name" in value:
66+
self.name = value["name"]
67+
continue
68+
updateAttribute = getattr(self, key)
69+
if isinstance(updateAttribute, dict):
70+
updateAttribute.update(value)
71+
setattr(self, key, updateAttribute)
72+
else:
73+
setattr(self, key, value)
74+
streamMessage = {"creationtime": datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"),
75+
"data": [self.getV2Api()],
76+
"id": str(uuid.uuid4()),
77+
"type": "update"
78+
}
79+
StreamEvent(streamMessage)
80+
81+
def save(self):
82+
result = {"id": self.id_v2, "metadata": {"name": self.name}, "configuration": self.configuration, "enabled": self.enabled, "active": self.active,
83+
"script_id": self.script_id}
84+
if self.name != None:
85+
result["metadata"] = {"name": self.name}
86+
87+
return result
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
import uuid
2+
import logManager
3+
import weakref
4+
from datetime import datetime, timezone
5+
from HueObjects import genV2Uuid, v1StateToV2, v2StateToV1, setGroupAction, StreamEvent
6+
7+
logging = logManager.logger.get_logger(__name__)
8+
9+
class EntertainmentConfiguration():
10+
def __init__(self, data):
11+
self.name = data["name"] if "name" in data else "Group " + \
12+
data["id_v1"]
13+
self.id_v1 = data["id_v1"]
14+
self.id_v2 = data["id_v2"] if "id_v2" in data else genV2Uuid()
15+
self.configuration_type = data["configuration_type"] if "configuration_type" in data else "3dspace"
16+
self.lights = []
17+
self.action = {"on": False, "bri": 100, "hue": 0, "sat": 254, "effect": "none", "xy": [
18+
0.0, 0.0], "ct": 153, "alert": "none", "colormode": "xy"}
19+
self.sensors = []
20+
self.type = data["type"] if "type" in data else "Entertainment"
21+
self.configuration_type = data["configuration_type"] if "configuration_type" in data else "screen"
22+
self.locations = weakref.WeakKeyDictionary()
23+
self.stream = {"proxymode": "auto",
24+
"proxynode": "/bridge", "active": False, "owner": None}
25+
self.state = {"all_on": False, "any_on": False}
26+
self.dxState = {"all_on": None, "any_on": None}
27+
28+
streamMessage = {"creationtime": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
29+
"data": [self.getV2Api()],
30+
"id": str(uuid.uuid4()),
31+
"type": "add"
32+
}
33+
StreamEvent(streamMessage)
34+
35+
def __del__(self):
36+
# Groupper light
37+
streamMessage = {"creationtime": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
38+
"data": [{"id": self.id_v2, "type": "grouped_light"}],
39+
"id": str(uuid.uuid4()),
40+
"type": "delete"
41+
}
42+
streamMessage["id_v1"] = "/groups/" + self.id_v1
43+
StreamEvent(streamMessage)
44+
### Entertainment area ###
45+
streamMessage = {"creationtime": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
46+
"data": [{"id": self.getV2Api()["id"], "type": "entertainment_configuration"}],
47+
"id": str(uuid.uuid4()),
48+
"type": "delete"
49+
}
50+
streamMessage["id_v1"] = "/groups/" + self.id_v1
51+
StreamEvent(streamMessage)
52+
logging.info(self.name + " entertainment area was destroyed.")
53+
54+
def add_light(self, light):
55+
self.lights.append(weakref.ref(light))
56+
self.locations[light] = [{"x": 0, "y": 0, "z": 0}]
57+
58+
def update_attr(self, newdata):
59+
if "lights" in newdata: # update of the lights must be done using add_light function
60+
del newdata["lights"]
61+
if "locations" in newdata: # update of the locations must be done directly from restful
62+
del newdata["locations"]
63+
for key, value in newdata.items():
64+
updateAttribute = getattr(self, key)
65+
if isinstance(updateAttribute, dict):
66+
updateAttribute.update(value)
67+
setattr(self, key, updateAttribute)
68+
else:
69+
setattr(self, key, value)
70+
streamMessage = {"creationtime": datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ"),
71+
"data": [self.getV2Api()],
72+
"id": str(uuid.uuid4()),
73+
"type": "update"
74+
}
75+
StreamEvent(streamMessage)
76+
77+
def update_state(self):
78+
all_on = True
79+
any_on = False
80+
if len(self.lights) == 0:
81+
all_on = False
82+
for light in self.lights:
83+
if light():
84+
if light().state["on"]:
85+
any_on = True
86+
else:
87+
all_on = False
88+
return {"all_on": all_on, "any_on": any_on}
89+
90+
def getV2GroupedLight(self):
91+
result = {}
92+
result["alert"] = {
93+
"action_values": [
94+
"breathe"
95+
]
96+
}
97+
result["id"] = self.id_v2
98+
result["id_v1"] = "/groups/" + self.id_v1
99+
result["on"] = {"on": self.update_state()["any_on"]}
100+
result["type"] = "grouped_light"
101+
return result
102+
103+
def getV1Api(self):
104+
result = {}
105+
result["name"] = self.name
106+
lights = []
107+
for light in self.lights:
108+
if light():
109+
lights.append(light().id_v1)
110+
sensors = []
111+
for sensor in self.sensors:
112+
if sensor():
113+
sensors.append(sensor().id_v1)
114+
result["lights"] = lights
115+
result["sensors"] = sensors
116+
result["type"] = self.type
117+
result["state"] = self.update_state()
118+
result["recycle"] = False
119+
class_type = "TV"
120+
if self.configuration_type == "3dspace":
121+
class_type == "Free"
122+
result["class"] = class_type
123+
result["action"] = self.action
124+
125+
result["locations"] = {}
126+
locations = list(self.locations.items())
127+
for light, location in locations:
128+
if light.id_v1 in lights:
129+
result["locations"][light.id_v1] = [
130+
location[0]["x"], location[0]["y"], location[0]["z"]]
131+
result["stream"] = self.stream
132+
return result
133+
134+
def getV2Api(self):
135+
136+
gradienStripPositions = [{"x": -0.4000000059604645, "y": 0.800000011920929, "z": -0.4000000059604645},
137+
{"x": -0.4000000059604645,
138+
"y": 0.800000011920929, "z": 0.0},
139+
{"x": -0.4000000059604645, "y": 0.800000011920929,
140+
"z": 0.4000000059604645},
141+
{"x": 0.0, "y": 0.800000011920929,
142+
"z": 0.4000000059604645},
143+
{"x": 0.4000000059604645, "y": 0.800000011920929,
144+
"z": 0.4000000059604645},
145+
{"x": 0.4000000059604645,
146+
"y": 0.800000011920929, "z": 0.0},
147+
{"x": 0.4000000059604645, "y": 0.800000011920929, "z": -0.4000000059604645}]
148+
149+
result = {
150+
"configuration_type": self.configuration_type,
151+
"locations": {
152+
"service_locations": []
153+
},
154+
"metadata": {
155+
"name": self.name
156+
},
157+
"id_v1": "/groups/" + self.id_v1,
158+
"stream_proxy": {
159+
"mode": "auto",
160+
"node": {
161+
"rid": str(uuid.uuid5(
162+
uuid.NAMESPACE_URL, self.lights[0]().id_v2 + 'entertainment')) if len(self.lights) > 0 else None,
163+
"rtype": "entertainment"
164+
}
165+
},
166+
"light_services": [],
167+
"channels": [],
168+
"id": str(uuid.uuid5(uuid.NAMESPACE_URL, self.id_v2 + 'entertainment_configuration')),
169+
"type": "entertainment_configuration",
170+
"name": self.name,
171+
"status": "active" if self.stream["active"] else "inactive"
172+
}
173+
if self.stream["active"]:
174+
result["active_streamer"] = {"rid": self.stream["owner"], "rtype": "auth_v1"}
175+
channel_id = 0
176+
for light in self.lights:
177+
if light():
178+
result["light_services"].append(
179+
{"rtype": "light", "rid": light().id_v2})
180+
entertainmentUuid = str(uuid.uuid5(
181+
uuid.NAMESPACE_URL, light().id_v2 + 'entertainment'))
182+
result["locations"]["service_locations"].append({"equalization_factor": 1, "positions": self.locations[light()],
183+
"service": {"rid": entertainmentUuid, "rtype": "entertainment"}, "position": self.locations[light()][0]})
184+
185+
loops = 1
186+
gradientStrip = False
187+
if light().modelid in ["LCX001", "LCX002", "LCX003"]:
188+
loops = len(gradienStripPositions)
189+
elif light().modelid in ["915005987201", "LCX004", "LCX006"]:
190+
loops = len(self.locations[light()])
191+
for x in range(loops):
192+
print("x:", x)
193+
channel = {
194+
"channel_id": channel_id,
195+
"members": [
196+
{
197+
"index": x,
198+
"service": {
199+
"rid": entertainmentUuid,
200+
"rtype": "entertainment"
201+
}
202+
}
203+
]
204+
}
205+
if light().modelid in ["LCX001", "LCX002", "LCX003"]:
206+
channel["position"] = {"x": gradienStripPositions[x]["x"],
207+
"y": gradienStripPositions[x]["y"], "z": gradienStripPositions[x]["z"]}
208+
elif light().modelid in ["915005987201", "LCX004", "LCX006"]:
209+
if x == 0:
210+
channel["position"] = {"x": self.locations[light(
211+
)][0]["x"], "y": self.locations[light()][0]["y"], "z": self.locations[light()][0]["z"]}
212+
elif x == 2:
213+
channel["position"] = {"x": self.locations[light(
214+
)][1]["x"], "y": self.locations[light()][1]["y"], "z": self.locations[light()][1]["z"]}
215+
else:
216+
channel["position"] = {"x": (self.locations[light()][0]["x"] + self.locations[light()][1]["x"]) / 2, "y": (self.locations[light(
217+
)][0]["y"] + self.locations[light()][1]["y"]) / 2, "z": (self.locations[light()][0]["z"] + self.locations[light()][1]["z"]) / 2}
218+
else:
219+
channel["position"] = {"x": self.locations[light(
220+
)][0]["x"], "y": self.locations[light()][0]["y"], "z": self.locations[light()][0]["z"]}
221+
222+
result["channels"].append(channel)
223+
channel_id += 1
224+
225+
return result
226+
227+
def setV2Action(self, state):
228+
v1State = v2StateToV1(state)
229+
setGroupAction(self, v1State)
230+
self.genStreamEvent(state)
231+
232+
def setV1Action(self, state, scene=None):
233+
setGroupAction(self, state, scene)
234+
v2State = v1StateToV2(state)
235+
self.genStreamEvent(v2State)
236+
237+
def genStreamEvent(self, v2State):
238+
streamMessage = {"creationtime": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
239+
"data": [{"id": self.id_v2, "type": "grouped_light"}],
240+
"id": str(uuid.uuid4()),
241+
"type": "update"
242+
}
243+
streamMessage["id_v1"] = "/groups/" + self.id_v1
244+
streamMessage.update(v2State)
245+
StreamEvent(streamMessage)
246+
247+
def getObjectPath(self):
248+
return {"resource": "groups", "id": self.id_v1}
249+
250+
def save(self):
251+
result = {"id_v2": self.id_v2, "name": self.name, "configuration_type": self.configuration_type,
252+
"lights": [], "action": self.action, "type": self.type, "configuration_type": self.configuration_type}
253+
for light in self.lights:
254+
if light():
255+
result["lights"].append(light().id_v1)
256+
result["locations"] = {}
257+
locations = list(self.locations.items())
258+
for light, location in locations:
259+
if light.id_v1 in result["lights"]:
260+
result["locations"][light.id_v1] = location
261+
return result

0 commit comments

Comments
 (0)