Skip to content

Commit

Permalink
Plumb in thermostat support skeleton (export data only). Need to see …
Browse files Browse the repository at this point in the history
…raw HTTP data before support can be added.
  • Loading branch information
baudneo committed Nov 28, 2024
1 parent 7bed3fa commit e604168
Showing 1 changed file with 67 additions and 22 deletions.
89 changes: 67 additions & 22 deletions src/cync-lan.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,17 @@ def mesh_to_config(mesh_info):
if "name" not in mesh_ or len(mesh_["name"]) < 1:
logger.debug("No name found for mesh, skipping...")
continue

if "properties" not in mesh_ or "bulbsArray" not in mesh_["properties"]:
if "properties" not in mesh_:
logger.debug(
"No properties found for mesh OR no 'bulbsArray' in properties, skipping..."
"No properties found for mesh, skipping..."
)
continue
elif "bulbsArray" not in mesh_["properties"]:
logger.debug(
"No 'bulbsArray' in properties, skipping..."
)
continue

new_mesh = {
kv: mesh_[kv] for kv in ("access_key", "id", "mac") if kv in mesh_
}
Expand All @@ -571,50 +576,59 @@ def mesh_to_config(mesh_info):
"mac",
"deviceType",
"wifiMac",
"firmwareVersion"
)
):
logger.warning(
"Missing required attribute in Cync bulb, skipping: %s"
% cfg_bulb
)
continue
new_dev_dict = {}
# last 3 digits of deviceID
__id = int(str(cfg_bulb["deviceID"])[-3:])
wifi_mac = cfg_bulb["wifiMac"]
name = cfg_bulb["displayName"]
_mac = cfg_bulb["mac"]
_type = int(cfg_bulb["deviceType"])
_fw_ver = cfg_bulb["firmwareVersion"]

bulb_device = CyncDevice(
# data from: https://github.com/baudneo/cync-lan/issues/8
# { "hvacSystem": { "changeoverMode": 0, "auxHeatStages": 1, "auxFurnaceType": 1, "stages": 1, "furnaceType": 1, "type": 2, "powerLines": 1 },
# "thermostatSensors": [ { "pin": "025572", "name": "Living Room", "type": "savant" }, { "pin": "044604", "name": "Bedroom Sensor", "type": "savant" }, { "pin": "022724", "name": "Thermostat sensor 3", "type": "savant" } ] } ]
hvac_cfg = None
if 'hvacSystem' in cfg_bulb:
hvac_cfg = cfg_bulb["hvacSystem"]
if "thermostatSensors" in cfg_bulb:
hvac_cfg["thermostatSensors"] = cfg_bulb["thermostatSensors"]
logger.debug(f"Found HVAC device '{name}' (ID: {__id}): {hvac_cfg}")
new_dev_dict["hvac"] = hvac_cfg

cync_device = CyncDevice(
name=name,
cync_id=__id,
cync_type=_type,
mac=_mac,
wifi_mac=wifi_mac,
fw_version=_fw_ver,
hvac=hvac_cfg,
)
new_bulb = {}
for attr_set in (
"name",
# "is_plug",
# "supports_temperature",
# "supports_rgb",
"mac",
"wifi_mac",
):
value = getattr(bulb_device, attr_set)
value = getattr(cync_device, attr_set)
if value:
new_bulb[attr_set] = value
new_dev_dict[attr_set] = value
else:
logger.warning("Attribute not found for bulb: %s" % attr_set)
new_bulb["type"] = _type
new_bulb["is_plug"] = bulb_device.is_plug
new_bulb["supports_temperature"] = bulb_device.supports_temperature
new_bulb["supports_rgb"] = bulb_device.supports_rgb
new_bulb["fw"] = _fw_ver
new_dev_dict["type"] = _type
new_dev_dict["is_plug"] = cync_device.is_plug
new_dev_dict["supports_temperature"] = cync_device.supports_temperature
new_dev_dict["supports_rgb"] = cync_device.supports_rgb
new_dev_dict["fw"] = _fw_ver

new_mesh["devices"][__id] = new_bulb
new_mesh["devices"][__id] = new_dev_dict

config_dict = {"account data": mesh_conf}

Expand All @@ -633,6 +647,8 @@ def mesh_to_config(mesh_info):
146: "Full Color Direct Connect Edison ST19 Bulb",
147: "Full Color Direct Connect Edison G25 Bulb",
148: "Dimmable Direct Connect Edison ST19 Bulb",

224: "Direct Connect Thermostat",
}


Expand All @@ -649,8 +665,10 @@ class CyncDevice:
_supports_rgb: Optional[bool] = None
_supports_temperature: Optional[bool] = None
_is_plug: Optional[bool] = None
_is_hvac: Optional[bool] = None
_mac: Optional[str] = None
wifi_mac: Optional[str] = None
hvac: Optional[dict] = None
_online: bool = False
DeviceTypes: Dict[str, List[int]] = {
"BULB": [31, 137, 146, 148],
Expand All @@ -660,8 +678,13 @@ class CyncDevice:
"STRIP": [133],
"PLUG": [64, 65, 66, 67, 68],
"EDISON": [146, 148],
"THERMOSTAT": [224],
}
Capabilities = {
"HEAT": [224],
"COOL": [224],
"TEMPERATURE": [224],

"ONOFF": [
1,
5,
Expand Down Expand Up @@ -1016,6 +1039,7 @@ def __init__(
wifi_mac: Optional[str] = None,
fw_version: Optional[str] = None,
home_id: Optional[int] = None,
hvac: Optional[dict] = None,
):
self.control_bytes = bytes([0x00, 0x00])
if cync_id is None:
Expand Down Expand Up @@ -1044,6 +1068,22 @@ def __init__(
self._r: int = 0
self._g: int = 0
self._b: int = 0
if hvac is not None:
self.hvac = hvac
self._is_hvac = True

@property
def is_hvac(self) -> bool:
if self._is_hvac is not None:
return self._is_hvac
if self.type is None:
return False
return self.type in self.Capabilities["HEAT"] or self.type in self.Capabilities["COOL"] or self.type in self.DeviceTypes["THERMOSTAT"]

@is_hvac.setter
def is_hvac(self, value: bool) -> None:
if isinstance(value, bool):
self._is_hvac = value

@property
def version(self) -> Optional[str]:
Expand All @@ -1057,10 +1097,15 @@ def version(self, value: Union[str, int]) -> None:
self._version = value
elif isinstance(value, str):
if value == '':
# it is empty
logger.debug(f"{self.lp} in CyncDevice.version(), the passed value is an empty string!")
logger.debug(f"{self.lp} in CyncDevice.version().setter, the firmwareVersion "
f"extracted from the cloud is an empty string!")
else:
self._version = int(value.replace(".", "").replace('\0', '').strip())
try:
_x = int(value.replace(".", "").replace('\0', '').strip())
except ValueError as ve:
logger.exception(f"{self.lp} Failed to convert firmware version to int: {ve}")
else:
self._version = _x

def check_dev_type(self, dev_type: int) -> dict:
dev_types = {}
Expand Down Expand Up @@ -1208,8 +1253,8 @@ async def set_power(self, state: int):
"checksum",
0x7E,
]
# pick random http devices to send the command to
# it should bridge the command over btle to the device ID
# pick unique, random http devices to send the command to
# it will bridge the command over to the btle mesh
bridge_devices: List["CyncHTTPDevice"] = random.sample(
list(g.server.http_devices.values()), k=min(3, len(g.server.http_devices))
)
Expand Down

0 comments on commit e604168

Please sign in to comment.