💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -16,7 +16,12 @@ backend or a different account.
|
|||||||
## 2. Govee — blocks #620 device data
|
## 2. Govee — blocks #620 device data
|
||||||
Cloud API sees zero devices (suspect BLE-only sensors).
|
Cloud API sees zero devices (suspect BLE-only sensors).
|
||||||
- [ ] Model numbers of your Govee temp sensors / lights:
|
- [ ] Model numbers of your Govee temp sensors / lights:
|
||||||
- [ ] Govee app account email + password (thermometer readings require it):
|
- [x] Govee app account email + password (thermometer readings require it):
|
||||||
|
|
||||||
|
**Agent (2026-09-02):** both accounts received, stored 0600 in
|
||||||
|
`~/.creds/govee.env`. But us.govee.com is a JS app the agent can't drive.
|
||||||
|
One human click needed: log in at us.govee.com → "Apply for API Key" →
|
||||||
|
paste the key here (or append `GOVEE_API_KEY=` to `~/.creds/govee.env`).
|
||||||
|
|
||||||
## 3. HomeKit codes — blocks #619 (ecobee + front-door lock)
|
## 3. HomeKit codes — blocks #619 (ecobee + front-door lock)
|
||||||
- [ ] ecobee HomeKit setup code (8-digit, on paperwork/box if not the unit):
|
- [ ] ecobee HomeKit setup code (8-digit, on paperwork/box if not the unit):
|
||||||
@@ -73,5 +78,11 @@ UniFi UI → Settings → System → Advanced → Integrations → API Keys →
|
|||||||
## 9. iDRAC/IPMI credentials (added 2026-09-02) — blocks #625
|
## 9. iDRAC/IPMI credentials (added 2026-09-02) — blocks #625
|
||||||
Both OOB ports are live but predate Redfish; IPMI (623/UDP) is the only data
|
Both OOB ports are live but predate Redfish; IPMI (623/UDP) is the only data
|
||||||
path. Temp + power monitoring for tsys6/tsys7 needs one of:
|
path. Temp + power monitoring for tsys6/tsys7 needs one of:
|
||||||
- [ ] iDRAC root password for both, or
|
- [x] iDRAC root password for both, or
|
||||||
- [ ] a read-only IPMI account (name + password), pasted here or into ~/.creds/idrac.env
|
|
||||||
|
**Agent (2026-09-02):** creds worked — BOTH iDRAC SNMP agents now live.
|
||||||
|
tsys7: community set to kn3lmgmt (verified). tsys6: agent enabled, but fw
|
||||||
|
1.41 refuses racadm community changes (stays `public`). Pick one:
|
||||||
|
- flip it in the iDRAC6 web UI (needs a TLS1.0-capable browser), or
|
||||||
|
- upgrade iDRAC6 firmware (1.41 → 2.9x) then racadm set, or
|
||||||
|
- accept `public` on the isolated OOB LAN for now
|
||||||
|
|||||||
@@ -0,0 +1,101 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""mdns-browse: one-shot multicast mDNS enumeration from this vantage.
|
||||||
|
|
||||||
|
Sends PTR queries for the DNS-SD service-enumeration name plus common
|
||||||
|
service types, listens briefly, prints every answer record. Stdlib only.
|
||||||
|
Diagnostic tool for #619 (WiFi-side multicast reachability)."""
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
MDNS_GROUP = "224.0.0.251"
|
||||||
|
MDNS_PORT = 5353
|
||||||
|
LISTEN_SECONDS = float(sys.argv[1]) if len(sys.argv) > 1 else 6.0
|
||||||
|
TYPES = {
|
||||||
|
1: "A", 28: "AAAA", 12: "PTR", 16: "TXT", 33: "SRV", 47: "NONE",
|
||||||
|
}
|
||||||
|
QUERIES = [
|
||||||
|
"_services._dns-sd._udp.local",
|
||||||
|
"_hap._tcp.local",
|
||||||
|
"_airplay._tcp.local",
|
||||||
|
"_googlecast._tcp.local",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def encode_name(name):
|
||||||
|
out = b""
|
||||||
|
for part in name.split("."):
|
||||||
|
out += bytes([len(part)]) + part.encode("latin1")
|
||||||
|
return out + b"\x00"
|
||||||
|
|
||||||
|
|
||||||
|
def read_name(data, off):
|
||||||
|
parts = []
|
||||||
|
seen = set()
|
||||||
|
while True:
|
||||||
|
if off in seen or len(seen) > 64:
|
||||||
|
return ".".join(parts), off
|
||||||
|
seen.add(off)
|
||||||
|
length = data[off]
|
||||||
|
if length == 0:
|
||||||
|
off += 1
|
||||||
|
break
|
||||||
|
if length & 0xC0:
|
||||||
|
ptr = struct.unpack(">H", data[off:off + 2])[0] & 0x3FFF
|
||||||
|
parts.append(read_name(data, ptr)[0])
|
||||||
|
off += 2
|
||||||
|
break
|
||||||
|
parts.append(data[off + 1:off + 1 + length].decode("latin1"))
|
||||||
|
off += 1 + length
|
||||||
|
return ".".join(parts), off
|
||||||
|
|
||||||
|
|
||||||
|
def build_query(names):
|
||||||
|
packet = struct.pack(">HHHHHH", 0, 0, len(names), 0, 0, 0)
|
||||||
|
for name in names:
|
||||||
|
packet += encode_name(name) + struct.pack(">HH", 12, 1)
|
||||||
|
return packet
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||||
|
sock.bind(("", MDNS_PORT))
|
||||||
|
mreq = socket.inet_aton(MDNS_GROUP) + socket.inet_aton("0.0.0.0")
|
||||||
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)
|
||||||
|
sock.settimeout(0.5)
|
||||||
|
sock.sendto(build_query(QUERIES), (MDNS_GROUP, MDNS_PORT))
|
||||||
|
deadline = time.time() + LISTEN_SECONDS
|
||||||
|
found = set()
|
||||||
|
while time.time() < deadline:
|
||||||
|
try:
|
||||||
|
data, addr = sock.recvfrom(16384)
|
||||||
|
except socket.timeout:
|
||||||
|
continue
|
||||||
|
an = struct.unpack(">H", data[6:8])[0]
|
||||||
|
off = 12
|
||||||
|
qd = struct.unpack(">H", data[4:6])[0]
|
||||||
|
try:
|
||||||
|
for _ in range(qd):
|
||||||
|
_, off = read_name(data, off)
|
||||||
|
off += 4
|
||||||
|
for _ in range(an):
|
||||||
|
name, name_end = read_name(data, off)
|
||||||
|
rtype, _rclass, ttl, rlen = struct.unpack(
|
||||||
|
">HHIH", data[name_end:name_end + 10])
|
||||||
|
detail = ""
|
||||||
|
if rtype == 12:
|
||||||
|
detail = " -> " + read_name(data, name_end + 10)[0]
|
||||||
|
found.add((TYPES.get(rtype, rtype), name, detail, addr[0]))
|
||||||
|
off = name_end + 10 + rlen
|
||||||
|
except (IndexError, struct.error):
|
||||||
|
continue
|
||||||
|
for rtype, name, detail, src in sorted(found):
|
||||||
|
print(f"{src:15} {rtype:5} {name}{detail}")
|
||||||
|
print(f"-- {len(found)} records from {LISTEN_SECONDS}s listen --")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user