-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds initial support for Dyson Big+Quiet devices (#17)
- Loading branch information
Showing
11 changed files
with
411 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from ..libdyson import DysonPureHotCool | ||
|
||
dev = DysonPureHotCool( | ||
serial='X3V-US-RKA0414A', | ||
credential='8qno2lc/IRy2xAFUem4u6AwBmk8YzWiDesTCS37VcSuphygAry+LDukJWfS1y93iYqGvWIaJ4xOWxu5r4OS+3g==', | ||
device_type="527K" | ||
) | ||
|
||
dev.connect('192.168.1.137') | ||
|
||
print(dev.humidity) | ||
|
||
print(dev.is_on) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
[ | ||
192.168.1.137: DysonDeviceInfo(active=None, serial='X3V-US-RKA0414A', name='Dyson Purifier Hot+Cool™', version='ECG2PF.34.00.003.0042', credential='8qno2lc/IRy2xAFUem4u6AwBmk8YzWiDesTCS37VcSuphygAry+LDukJWfS1y93iYqGvWIaJ4xOWxu5r4OS+3g==', auto_update=False, new_version_available=True, product_type='527K') | ||
DysonDeviceInfo(active=None, serial='N9R-US-PJB7094A', name='', version='ECG2PF.30.06.003.0002', credential='8xPhRU9+SwTOTyU1Fni0VLpjd/hrDCPb2oyqp1eOGM78TmGnd7pae6jNsYTH4qwMnpOOFt2C/6z+20FDfGibhw==', auto_update=False, new_version_available=False, product_type='527'), | ||
DysonDeviceInfo(active=None, serial='NM7-US-REA2128A', name='Downstairs', version='21.04.03', credential='bRSU6+ck9EVZ4PtCUaqJp/XtbEzxEBgGLvPwg3XFJWRQvGMJYKKY8SjFF+153WQ3/YLmy3mUeB2glO6efEHZIQ==', auto_update=True, new_version_available=False, product_type='475'), | ||
DysonDeviceInfo(active=None, serial='NM7-US-REA2583A', name='Dyson Fan', version='21.04.03', credential='qQF4gMdA6Pg8OvY0OKmjpSOq/PAdcnD/Qv3KW8ecrLV3P82iMf9fK/TJBBpw0/2r7uovH0AwXL/WLHJYWpkNvg==', auto_update=False, new_version_available=False, product_type='475'), | ||
] | ||
f | ||
Environmental: | ||
{ | ||
'hact': '0053', humidity | ||
'hcho': 'NONE', Formaldehyde | ||
'hchr': 'NONE', High_Res Formaldehyde | ||
'noxl': '0002', Nitrogen Dioxide | ||
'p10r': '0000', "High_res" pm10 | ||
'p25r': '0000', "High_res" pm25 | ||
'pm10': '0000', | ||
'pm25': '0000', | ||
'sltm': 'OFF', | ||
'tact': '2964', Temp | ||
'va10': '0008', Gen2 VOC | ||
} | ||
{"msg":"ENVIRONMENTAL-CURRENT-SENSOR-DATA","time":"2023-06-11T01:59:08.000Z","data":{"tact":"2958","hact":"0052","pm25":"0002","pm10":"0001","va10":"0008","noxl":"0003","p25r":"0003","p10r":"0003","hcho":"NONE","hchr":"NONE","sltm":"OFF"}} | ||
|
||
State: | ||
{ | ||
'fpwr': 'ON', Fan Power | ||
'auto': 'OFF', Auto | ||
'oscs': 'OFF', Oscillation something? | ||
'oson': 'OFF', Oscillation something again | ||
'nmod': 'OFF', ??? | ||
'rhtm': 'ON', Continuous Monitoring | ||
'fnst': 'FAN', Fan State | ||
'ercd': '32U2', Error Code - 32U2 is probably filter(s) | ||
'wacd': 'NONE', Warning Code | ||
'nmdv': '0004', Night Mode Speed | ||
'fnsp': '0008', Fan Speed | ||
'bril': '0002', ??? | ||
'corf': 'OFF', | ||
'cflr': 'INV', Carbon Filter Life | ||
'hflr': '0073', Hepa Filter Life | ||
'cflt': 'NONE', ??? | ||
'hflt': 'GCOM', ??? | ||
'sltm': 'OFF', Sleep Timer | ||
'osal': '0135', Oscillation Angle Low | ||
'osau': '0225', Oscillation Angle High | ||
'ancp': 'CUST', Oscillation Mode | ||
'hmod': 'OFF', Heat Mode | ||
'hmax': '2936', Heat Target | ||
'tilt': 'OK', Tilt | ||
'hsta': 'OFF', Heat State | ||
'psta': 'OFF', | ||
'fdir': 'ON', Front Airflow | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
ppb = 28 | ||
ppm = ppb / 1000 | ||
|
||
air = 24.45 | ||
|
||
# Mol weight | ||
no2 = 46.005 | ||
|
||
print((ppm * no2) / air) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import signal | ||
import sys | ||
import time | ||
|
||
import paho.mqtt.client as mqtt | ||
|
||
|
||
def on_connect(client, userdata, flags, rc): | ||
print("Connected to MQTT broker. Press Ctrl+C to exit.") | ||
client.subscribe("#") | ||
|
||
|
||
def on_message(client, userdata, msg): | ||
print("Received message on topic: {}".format(msg.topic)) | ||
print("Message: {}".format(msg.payload.decode())) | ||
print("---------------------") | ||
|
||
|
||
def on_signal(signum, frame): | ||
print("\nReceived SIGTERM signal. Disconnecting from MQTT broker...") | ||
client.disconnect() | ||
sys.exit(0) | ||
|
||
|
||
# Set up MQTT client | ||
client = mqtt.Client(client_id="mqtt-subscriber") | ||
client.username_pw_set("X3V-US-RKA0414A", "8qno2lc/IRy2xAFUem4u6AwBmk8YzWiDesTCS37VcSuphygAry+LDukJWfS1y93iYqGvWIaJ4xOWxu5r4OS+3g==") | ||
|
||
# Set up signal handler for SIGTERM | ||
signal.signal(signal.SIGTERM, on_signal) | ||
|
||
# Set up MQTT client callbacks | ||
client.on_connect = on_connect | ||
client.on_message = on_message | ||
|
||
# Connect to MQTT broker | ||
client.connect("192.168.1.137", 1883, 60) | ||
|
||
# Start the MQTT loop | ||
client.loop_start() | ||
|
||
try: | ||
# Keep the script running until SIGTERM is received | ||
while True: | ||
time.sleep(1) | ||
except KeyboardInterrupt: | ||
# Handle Ctrl+C | ||
print("\nInterrupted by user. Disconnecting from MQTT broker...") | ||
client.disconnect() | ||
sys.exit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
ppb = 18 | ||
ppm = ppb / 1000 | ||
mol = 46.005 | ||
|
||
air = 24.45 | ||
|
||
|
||
print((ppm * mol) / air) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
"""Dyson Pure Cool fan.""" | ||
|
||
from abc import abstractmethod | ||
from typing import Optional | ||
|
||
from .dyson_device import DysonFanDevice | ||
|
||
|
||
class DysonBigQuiet(DysonFanDevice): | ||
"""Dyson Pure Cool series base class.""" | ||
|
||
@property | ||
def is_on(self) -> bool: | ||
"""Return if the device is on.""" | ||
return self._get_field_value(self._status, "fpwr") == "ON" | ||
|
||
@property | ||
def auto_mode(self) -> bool: | ||
"""Return auto mode status.""" | ||
return self._get_field_value(self._status, "auto") == "ON" | ||
|
||
@property | ||
def front_airflow(self) -> bool: | ||
"""Return if airflow from front is on.""" | ||
return self._get_field_value(self._status, "fdir") == "ON" | ||
|
||
@property | ||
def night_mode_speed(self) -> int: | ||
"""Return speed in night mode.""" | ||
return int(self._get_field_value(self._status, "nmdv")) | ||
|
||
@property | ||
def carbon_filter_life(self) -> Optional[int]: | ||
"""Return carbon filter life in percentage.""" | ||
filter_life = self._get_field_value(self._status, "cflr") | ||
if filter_life == "INV": | ||
return None | ||
return int(filter_life) | ||
|
||
@property | ||
def hepa_filter_life(self) -> Optional[int]: | ||
"""Return HEPA filter life in percentage.""" | ||
return int(self._get_field_value(self._status, "hflr")) | ||
|
||
@property | ||
def particulate_matter_2_5(self): | ||
"""Return PM 2.5 in micro grams per cubic meter.""" | ||
return int(self._get_environmental_field_value("pm25")) | ||
|
||
@property | ||
def particulate_matter_10(self): | ||
"""Return PM 2.5 in micro grams per cubic meter.""" | ||
return int(self._get_environmental_field_value("pm10")) | ||
|
||
@property | ||
def volatile_organic_compounds(self) -> float: | ||
"""Return the index value for VOC""" | ||
return self._get_environmental_field_value("va10", divisor=10) | ||
|
||
@property | ||
def nitrogen_dioxide(self) -> float: | ||
"""Return the index value for nitrogen.""" | ||
return self._get_environmental_field_value("noxl", divisor=10) | ||
|
||
def turn_on(self) -> None: | ||
"""Turn on the device.""" | ||
self._set_configuration(fpwr="ON") | ||
|
||
def turn_off(self) -> None: | ||
"""Turn off the device.""" | ||
self._set_configuration(fpwr="OFF") | ||
|
||
def _set_speed(self, speed: int) -> None: | ||
self._set_configuration(fpwr="ON", fnsp=f"{speed:04d}") | ||
|
||
def enable_auto_mode(self) -> None: | ||
"""Turn on auto mode.""" | ||
self._set_configuration(auto="ON") | ||
|
||
def disable_auto_mode(self) -> None: | ||
"""Turn off auto mode.""" | ||
self._set_configuration(auto="OFF") | ||
|
||
def enable_continuous_monitoring(self) -> None: | ||
"""Turn on continuous monitoring.""" | ||
self._set_configuration( | ||
fpwr="ON" if self.is_on else "OFF", # Not sure about this | ||
rhtm="ON", | ||
) | ||
|
||
def disable_continuous_monitoring(self) -> None: | ||
"""Turn off continuous monitoring.""" | ||
self._set_configuration( | ||
fpwr="ON" if self.is_on else "OFF", | ||
rhtm="OFF", | ||
) | ||
|
||
def enable_front_airflow(self) -> None: | ||
"""Turn on front airflow.""" | ||
self._set_configuration(fdir="ON") | ||
|
||
def disable_front_airflow(self) -> None: | ||
"""Turn off front airflow.""" | ||
self._set_configuration(fdir="OFF") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[metadata] | ||
name = libdyson-neon | ||
version = 1.1.0 | ||
version = 1.2.0 | ||
author = The libdyson Working Group | ||
author_email = [email protected] | ||
license = MIT License | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.