Skip to content

Commit

Permalink
Add dummy, update wled.
Browse files Browse the repository at this point in the history
Update github workflow.
Update wled behavior.
Fix linkbutton in hue essentials.
Add dummy light.
Make mdns in line with philips.
  • Loading branch information
hendriksen-mark committed Dec 1, 2024
1 parent 5515247 commit 14008aa
Show file tree
Hide file tree
Showing 12 changed files with 61 additions and 42 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
arch_friendly: armv6
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Enable qemu
run: |
Expand Down Expand Up @@ -380,6 +380,6 @@ jobs:
matrix:
arch: [amd64, armv7, arm64, armv6]
steps:
- uses: geekyeggo/delete-artifact@v1
- uses: geekyeggo/delete-artifact@v5
with:
name: ci-${{ matrix.arch }}-${{ github.run_number }}.tar
23 changes: 19 additions & 4 deletions BridgeEmulator/configManager/configHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import weakref
from copy import deepcopy
from HueObjects import Light, Group, EntertainmentConfiguration, Scene, ApiUser, Rule, ResourceLink, Schedule, Sensor, BehaviorInstance, SmartScene
from lights.protocols import wled
try:
from time import tzset
except ImportError:
Expand All @@ -28,6 +29,16 @@ def _write_yaml(path, contents):
with open(path, 'w', encoding="utf-8") as fp:
yaml.dump(contents, fp , Dumper=NoAliasDumper, allow_unicode=True, sort_keys=False )

def reAddWled(old_light):
detectedLights = []
wled.discover(detectedLights, old_light["protocol_cfg"]["ip"])
for light in detectedLights:
if light["name"] == old_light["name"] and light["protocol_cfg"]["ip"] == old_light["protocol_cfg"]["ip"] and light["protocol_cfg"]["segmentId"] == old_light["protocol_cfg"]["segmentId"]:
logging.info("Update Wled " + light["name"])
old_light["protocol_cfg"]["ledCount"] = light["protocol_cfg"]["ledCount"]
old_light["protocol_cfg"]["segment_start"] = light["protocol_cfg"]["segment_start"]
old_light["protocol_cfg"]["udp_port"] = light["protocol_cfg"]["udp_port"]
return old_light

class Config:
yaml_config = None
Expand Down Expand Up @@ -106,9 +117,11 @@ def load_config(self):
}

if int(config["swversion"]) < 1958077010:
config["swversion"] = "1965111030"
config["swversion"] = "1967054020"
if float(config["apiversion"][:3]) < 1.56:
config["apiversion"] = "1.65.0"
config["apiversion"] = "1.67.0"
if "linkbutton" not in config or type(config["linkbutton"]) == bool or "lastlinkbuttonpushed" not in config["linkbutton"]:
config["linkbutton"] = {"lastlinkbuttonpushed": 1599398980}

self.yaml_config["config"] = config
else:
Expand All @@ -122,10 +135,10 @@ def load_config(self):
"alarm":{"enabled": False,"lasttriggered": 0},
"port":{"enabled": False,"ports": [80]},
"apiUsers":{},
"apiversion":"1.65.0",
"apiversion":"1.67.0",
"name":"DiyHue Bridge",
"netmask":"255.255.255.0",
"swversion":"1965111030",
"swversion":"1967054020",
"timezone": "Europe/London",
"linkbutton":{"lastlinkbuttonpushed": 1599398980},
"users":{"[email protected]":{"password":"pbkdf2:sha256:150000$bqqXSOkI$199acdaf81c18f6ff2f29296872356f4eb78827784ce4b3f3b6262589c788742"}},
Expand Down Expand Up @@ -166,6 +179,8 @@ def load_config(self):
if os.path.exists(self.configDir + "/lights.yaml"):
lights = _open_yaml(self.configDir + "/lights.yaml")
for light, data in lights.items():
if data["protocol"] == "wled" and "segment_start" not in data["protocol_cfg"]:
data = reAddWled(data)
data["id_v1"] = light
self.yaml_config["lights"][light] = Light.Light(data)
#self.yaml_config["groups"]["0"].add_light(self.yaml_config["lights"][light])
Expand Down
3 changes: 3 additions & 0 deletions BridgeEmulator/flaskUI/restful.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,9 @@ def put(self, username, resource):
if "loglevel" in putDict:
logManager.logger.configure_logger(putDict["loglevel"])
logging.info("Change log level to: " + str(logManager.logger.get_level_name()))
if "linkbutton" in putDict:
if type(putDict["linkbutton"]) == bool:
bridgeConfig["config"]["linkbutton"] = {"lastlinkbuttonpushed": datetime.now().timestamp()}

# build response list
responseList = []
Expand Down
6 changes: 3 additions & 3 deletions BridgeEmulator/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@ cp -r HueEmulator3.py githubInstall.sh HueObjects configManager flaskUI function

curl -sL https://github.com/diyhue/diyHueUI/releases/latest/download/DiyHueUI-release.zip -o diyHueUI.zip
unzip -qo diyHueUI.zip
mv index.html /opt/hue-emulator/flaskUI/templates/
cp -r static /opt/hue-emulator/flaskUI/
rm -r static
mv dist/index.html /opt/hue-emulator/flaskUI/templates/
cp -r dist/assets /opt/hue-emulator/flaskUI/
rm -r dist

cp hue-emulator.service /lib/systemd/system/
cd ../../
Expand Down
4 changes: 2 additions & 2 deletions BridgeEmulator/install_openwrt.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ curl -sL https://www.github.com/diyhue/diyHueUI/releases/latest/download/DiyHueU
wait
unzip -qo diyHueUI.zip -d diyhueUI
wait
mv diyhueUI/index.html /opt/hue-emulator/flaskUI/templates/
cp -r diyhueUI/static /opt/hue-emulator/flaskUI/
mv diyhueUI/dist/index.html /opt/hue-emulator/flaskUI/templates/
cp -r diyhueUI/dist/assets /opt/hue-emulator/flaskUI/

echo -e "\033[32m Creating certificate.\033[0m"
cd /opt/hue-emulator
Expand Down
1 change: 0 additions & 1 deletion BridgeEmulator/lights/discover.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ def iter_ips(port):
host = HOST_IP.split('.')
if scan_on_host_ip:
yield ('127.0.0.1', port)
return
for sub_addr in range(sub_ip_range_start, sub_ip_range_end + 1):
host[2] = str(sub_addr)
for addr in range(ip_range_start, ip_range_end + 1):
Expand Down
4 changes: 2 additions & 2 deletions BridgeEmulator/lights/protocols/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from lights.protocols import wled, hyperion, yeelight, tasmota, shelly, mi_box, hue, deconz, domoticz, tradfri, native, native_single, native_multi, esphome, mqtt, wiz, milight, homeassistant_ws, tpkasa, hue_bl, elgato
from lights.protocols import wled, hyperion, yeelight, tasmota, shelly, mi_box, hue, deconz, domoticz, tradfri, native, native_single, native_multi, esphome, mqtt, wiz, milight, homeassistant_ws, tpkasa, hue_bl, elgato, dummy

protocols = [wled, hyperion, yeelight, tasmota, shelly, mi_box, hue, deconz, domoticz, tradfri, native, native_single, native_multi, esphome, mqtt, wiz, milight, homeassistant_ws, tpkasa, hue_bl, elgato]
protocols = [wled, hyperion, yeelight, tasmota, shelly, mi_box, hue, deconz, domoticz, tradfri, native, native_single, native_multi, esphome, mqtt, wiz, milight, homeassistant_ws, tpkasa, hue_bl, elgato, dummy]
2 changes: 2 additions & 0 deletions BridgeEmulator/lights/protocols/dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def set_light(light, data):
pass
28 changes: 12 additions & 16 deletions BridgeEmulator/lights/protocols/wled.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def discover(detectedLights, device_ips):
logging.info('<WLED> discovery started')
ip_version = IPVersion.V4Only
zeroconf = Zeroconf(ip_version=ip_version)
services = ["_http._tcp.local."]
services = "_http._tcp.local."
browser = ServiceBrowser(zeroconf, services, handlers=[on_mdns_discover])
sleep(2)
if len(discovered_lights) == 0:
Expand Down Expand Up @@ -60,10 +60,12 @@ def discover(detectedLights, device_ips):
"modelid": modelid,
"protocol_cfg": {
"ip": x.ip,
"ledCount": x.ledCount,
"ledCount": x.segments[segmentid]["len"],
"mdns_name": device[1],
"mac": x.mac,
"segmentId": segmentid
"segmentId": segmentid,
"segment_start": x.segments[segmentid]["start"],
"udp_port": x.udpPort
}
})
segmentid = segmentid + 1
Expand Down Expand Up @@ -100,9 +102,9 @@ def send_light_data(c, light, data):
if k == "on":
# Handle on/off at light level
if v:
state["on"] = True
seg["on"] = True
else:
state["on"] = False
seg["on"] = False
elif k == "bri":
seg["bri"] = v+1
elif k == "ct":
Expand Down Expand Up @@ -172,20 +174,15 @@ def __init__(self, ip, mdns_name):

def getInitialState(self):
self.state = self.getLightState()
self.getSegments()
self.getLedCount()
self.getMacAddr()

def getLedCount(self):
self.getInfo()

def getInfo(self):
self.ledCount = self.state['info']['leds']['count']

def getMacAddr(self):
self.mac = ':'.join(self.state[
'info']['mac'][i:i+2] for i in range(0, 12, 2))

def getSegments(self):
self.segments = self.state['state']['seg']
self.segmentCount = len(self.segments)
self.udpPort = self.state['info']['udpport']

def getLightState(self):
with urllib.request.urlopen(self.url + '/json') as resp:
Expand All @@ -197,8 +194,7 @@ def getSegState(self, seg):
data = self.getLightState()['state']
seg = data['seg'][seg]
state['bri'] = seg['bri']
state['on'] = data['on'] # Get on/off at light level
state['bri'] = seg['bri']
state['on'] = seg['on']
# Weird division by zero when a color is 0
r = int(seg['col'][0][0])+1
g = int(seg['col'][0][1])+1
Expand Down
24 changes: 14 additions & 10 deletions BridgeEmulator/services/entertainment.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,10 +230,12 @@ def entertainmentService(group, user):
elif proto == "wled":
if light.protocol_cfg["ip"] not in wledLights:
wledLights[light.protocol_cfg["ip"]] = {}
wledLights[light.protocol_cfg["ip"]
]["ledCount"] = light.protocol_cfg["ledCount"]
wledLights[light.protocol_cfg["ip"]
]["color"] = [r, g, b]
if light.protocol_cfg["segmentId"] not in wledLights[light.protocol_cfg["ip"]]:
wledLights[light.protocol_cfg["ip"]][light.protocol_cfg["segmentId"]] = {}
wledLights[light.protocol_cfg["ip"]][light.protocol_cfg["segmentId"]]["ledCount"] = light.protocol_cfg["ledCount"]
wledLights[light.protocol_cfg["ip"]][light.protocol_cfg["segmentId"]]["start"] = light.protocol_cfg["segment_start"]
wledLights[light.protocol_cfg["ip"]][light.protocol_cfg["segmentId"]]["udp_port"] = light.protocol_cfg["udp_port"]
wledLights[light.protocol_cfg["ip"]][light.protocol_cfg["segmentId"]]["color"] = [r, g, b]
elif proto == "hue" and int(light.protocol_cfg["id"]) in hueGroupLights:
hueGroupLights[int(light.protocol_cfg["id"])] = [r,g,b]
else:
Expand Down Expand Up @@ -271,14 +273,16 @@ def entertainmentService(group, user):
auth = {'username':bridgeConfig["config"]["mqtt"]["mqttUser"], 'password':bridgeConfig["config"]["mqtt"]["mqttPassword"]}
publish.multiple(mqttLights, hostname=bridgeConfig["config"]["mqtt"]["mqttServer"], port=bridgeConfig["config"]["mqtt"]["mqttPort"], auth=auth)
if len(wledLights) != 0:
wled_udpmode = 2
wled_udpmode = 4 #DNRGB mode
wled_secstowait = 2
for ip in wledLights.keys():
udphead = [wled_udpmode, wled_secstowait]
color = wledLights[ip]["color"] * int(wledLights[ip]["ledCount"])
udpdata = bytes(udphead+color)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(udpdata, (ip.split(":")[0], 21324))
for segments in wledLights[ip]:
udphead = bytes([wled_udpmode, wled_secstowait])
start_seg = wledLights[ip][segments]["start"].to_bytes(2,"big")
color = bytes(wledLights[ip][segments]["color"] * int(wledLights[ip][segments]["ledCount"]))
udpdata = udphead+start_seg+color
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(udpdata, (ip.split(":")[0], wledLights[ip][segments]["udp_port"]))
if len(hueGroupLights) != 0:
h.send(hueGroupLights, hueGroup)
new_frame_time = time.time()
Expand Down
2 changes: 1 addition & 1 deletion BridgeEmulator/services/mdns.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def mdnsListener(ip, port, modelid, brigeid):

info = ServiceInfo(
"_hue._tcp.local.",
"DIYHue-" + brigeid + "._hue._tcp.local.",
"DIYHue-" + brigeid[-6:] + "._hue._tcp.local.",
addresses=[socket.inet_aton(ip)],
port=port,
properties=props,
Expand Down
2 changes: 1 addition & 1 deletion BridgeEmulator/services/stateFetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def syncWithLights(off_if_unreachable): #update Hue Bridge lights states
for key, light in bridgeConfig["lights"].items():
protocol_name = light.protocol
for protocol in protocols:
if "lights.protocols." + protocol_name == protocol.__name__ and protocol_name not in ["mqtt", "flex", "mi_box"]:
if "lights.protocols." + protocol_name == protocol.__name__ and protocol_name not in ["mqtt", "flex", "mi_box", "dummy"]:
try:
logging.debug("fetch " + light.name)
newState = protocol.get_light_state(light)
Expand Down

0 comments on commit 14008aa

Please sign in to comment.