Add update entity to RainMachine (#76100)
* Add update entity to RainMachine * Fix tests * Cleanup * Test missing controller diagnostics * Code review
This commit is contained in:
parent
dc30d97938
commit
ceecab9559
8 changed files with 882 additions and 140 deletions
|
@ -980,6 +980,7 @@ omit =
|
|||
homeassistant/components/rainmachine/model.py
|
||||
homeassistant/components/rainmachine/sensor.py
|
||||
homeassistant/components/rainmachine/switch.py
|
||||
homeassistant/components/rainmachine/update.py
|
||||
homeassistant/components/rainmachine/util.py
|
||||
homeassistant/components/raspyrfm/*
|
||||
homeassistant/components/recollect_waste/__init__.py
|
||||
|
|
|
@ -36,6 +36,8 @@ from homeassistant.util.network import is_ip_address
|
|||
from .config_flow import get_client_controller
|
||||
from .const import (
|
||||
CONF_ZONE_RUN_TIME,
|
||||
DATA_API_VERSIONS,
|
||||
DATA_MACHINE_FIRMWARE_UPDATE_STATUS,
|
||||
DATA_PROGRAMS,
|
||||
DATA_PROVISION_SETTINGS,
|
||||
DATA_RESTRICTIONS_CURRENT,
|
||||
|
@ -51,7 +53,13 @@ DEFAULT_SSL = True
|
|||
|
||||
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
|
||||
|
||||
PLATFORMS = [Platform.BINARY_SENSOR, Platform.BUTTON, Platform.SENSOR, Platform.SWITCH]
|
||||
PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.BUTTON,
|
||||
Platform.SENSOR,
|
||||
Platform.SWITCH,
|
||||
Platform.UPDATE,
|
||||
]
|
||||
|
||||
CONF_CONDITION = "condition"
|
||||
CONF_DEWPOINT = "dewpoint"
|
||||
|
@ -124,8 +132,10 @@ SERVICE_RESTRICT_WATERING_SCHEMA = SERVICE_SCHEMA.extend(
|
|||
)
|
||||
|
||||
COORDINATOR_UPDATE_INTERVAL_MAP = {
|
||||
DATA_PROVISION_SETTINGS: timedelta(minutes=1),
|
||||
DATA_API_VERSIONS: timedelta(minutes=1),
|
||||
DATA_MACHINE_FIRMWARE_UPDATE_STATUS: timedelta(seconds=15),
|
||||
DATA_PROGRAMS: timedelta(seconds=30),
|
||||
DATA_PROVISION_SETTINGS: timedelta(minutes=1),
|
||||
DATA_RESTRICTIONS_CURRENT: timedelta(minutes=1),
|
||||
DATA_RESTRICTIONS_UNIVERSAL: timedelta(minutes=1),
|
||||
DATA_ZONES: timedelta(seconds=15),
|
||||
|
@ -215,7 +225,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
data: dict = {}
|
||||
|
||||
try:
|
||||
if api_category == DATA_PROGRAMS:
|
||||
if api_category == DATA_API_VERSIONS:
|
||||
data = await controller.api.versions()
|
||||
elif api_category == DATA_MACHINE_FIRMWARE_UPDATE_STATUS:
|
||||
data = await controller.machine.get_firmware_update_status()
|
||||
elif api_category == DATA_PROGRAMS:
|
||||
data = await controller.programs.all(include_inactive=True)
|
||||
elif api_category == DATA_PROVISION_SETTINGS:
|
||||
data = await controller.provisioning.settings()
|
||||
|
@ -414,23 +428,32 @@ class RainMachineEntity(CoordinatorEntity):
|
|||
"""Initialize."""
|
||||
super().__init__(data.coordinators[description.api_category])
|
||||
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, data.controller.mac)},
|
||||
configuration_url=f"https://{entry.data[CONF_IP_ADDRESS]}:{entry.data[CONF_PORT]}",
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, data.controller.mac)},
|
||||
name=str(data.controller.name).capitalize(),
|
||||
manufacturer="RainMachine",
|
||||
model=(
|
||||
f"Version {data.controller.hardware_version} "
|
||||
f"(API: {data.controller.api_version})"
|
||||
),
|
||||
sw_version=data.controller.software_version,
|
||||
)
|
||||
self._attr_extra_state_attributes = {}
|
||||
self._attr_unique_id = f"{data.controller.mac}_{description.key}"
|
||||
self._entry = entry
|
||||
self._data = data
|
||||
self._version_coordinator = data.coordinators[DATA_API_VERSIONS]
|
||||
self.entity_description = description
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information about this controller."""
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self._data.controller.mac)},
|
||||
configuration_url=(
|
||||
f"https://{self._entry.data[CONF_IP_ADDRESS]}:"
|
||||
f"{self._entry.data[CONF_PORT]}"
|
||||
),
|
||||
connections={(dr.CONNECTION_NETWORK_MAC, self._data.controller.mac)},
|
||||
name=str(self._data.controller.name).capitalize(),
|
||||
manufacturer="RainMachine",
|
||||
model=(
|
||||
f"Version {self._version_coordinator.data['hwVer']} "
|
||||
f"(API: {self._version_coordinator.data['apiVer']})"
|
||||
),
|
||||
sw_version=self._version_coordinator.data["swVer"],
|
||||
)
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Respond to a DataUpdateCoordinator update."""
|
||||
|
@ -440,6 +463,11 @@ class RainMachineEntity(CoordinatorEntity):
|
|||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
await super().async_added_to_hass()
|
||||
self.async_on_remove(
|
||||
self._version_coordinator.async_add_listener(
|
||||
self._handle_coordinator_update, self.coordinator_context
|
||||
)
|
||||
)
|
||||
self.update_from_latest_data()
|
||||
|
||||
@callback
|
||||
|
|
|
@ -7,6 +7,8 @@ DOMAIN = "rainmachine"
|
|||
|
||||
CONF_ZONE_RUN_TIME = "zone_run_time"
|
||||
|
||||
DATA_API_VERSIONS = "api.versions"
|
||||
DATA_MACHINE_FIRMWARE_UPDATE_STATUS = "machine.firmware_update_status"
|
||||
DATA_PROGRAMS = "programs"
|
||||
DATA_PROVISION_SETTINGS = "provision.settings"
|
||||
DATA_RESTRICTIONS_CURRENT = "restrictions.current"
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
"""Diagnostics support for RainMachine."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
|
||||
from regenmaschine.errors import RequestError
|
||||
from regenmaschine.errors import RainMachineError
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
|
@ -17,7 +16,7 @@ from homeassistant.const import (
|
|||
from homeassistant.core import HomeAssistant
|
||||
|
||||
from . import RainMachineData
|
||||
from .const import DOMAIN
|
||||
from .const import DOMAIN, LOGGER
|
||||
|
||||
CONF_STATION_ID = "stationID"
|
||||
CONF_STATION_NAME = "stationName"
|
||||
|
@ -42,13 +41,11 @@ async def async_get_config_entry_diagnostics(
|
|||
"""Return diagnostics for a config entry."""
|
||||
data: RainMachineData = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
controller_tasks = {
|
||||
"versions": data.controller.api.versions(),
|
||||
"current_diagnostics": data.controller.diagnostics.current(),
|
||||
}
|
||||
controller_results = await asyncio.gather(
|
||||
*controller_tasks.values(), return_exceptions=True
|
||||
)
|
||||
try:
|
||||
controller_diagnostics = await data.controller.diagnostics.current()
|
||||
except RainMachineError:
|
||||
LOGGER.warning("Unable to download controller-specific diagnostics")
|
||||
controller_diagnostics = None
|
||||
|
||||
return {
|
||||
"entry": {
|
||||
|
@ -64,10 +61,6 @@ async def async_get_config_entry_diagnostics(
|
|||
},
|
||||
TO_REDACT,
|
||||
),
|
||||
"controller": {
|
||||
category: result
|
||||
for category, result in zip(controller_tasks, controller_results)
|
||||
if not isinstance(result, RequestError)
|
||||
},
|
||||
"controller_diagnostics": controller_diagnostics,
|
||||
},
|
||||
}
|
||||
|
|
102
homeassistant/components/rainmachine/update.py
Normal file
102
homeassistant/components/rainmachine/update.py
Normal file
|
@ -0,0 +1,102 @@
|
|||
"""Support for RainMachine updates."""
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
from regenmaschine.errors import RequestError
|
||||
|
||||
from homeassistant.components.update import (
|
||||
UpdateDeviceClass,
|
||||
UpdateEntity,
|
||||
UpdateEntityFeature,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import RainMachineData, RainMachineEntity
|
||||
from .const import DATA_MACHINE_FIRMWARE_UPDATE_STATUS, DOMAIN
|
||||
from .model import RainMachineEntityDescription
|
||||
|
||||
|
||||
class UpdateStates(Enum):
|
||||
"""Define an enum for update states."""
|
||||
|
||||
IDLE = 1
|
||||
CHECKING = 2
|
||||
DOWNLOADING = 3
|
||||
UPGRADING = 4
|
||||
ERROR = 5
|
||||
REBOOT = 6
|
||||
|
||||
|
||||
UPDATE_STATE_MAP = {
|
||||
1: UpdateStates.IDLE,
|
||||
2: UpdateStates.CHECKING,
|
||||
3: UpdateStates.DOWNLOADING,
|
||||
4: UpdateStates.UPGRADING,
|
||||
5: UpdateStates.ERROR,
|
||||
6: UpdateStates.REBOOT,
|
||||
}
|
||||
|
||||
|
||||
UPDATE_DESCRIPTION = RainMachineEntityDescription(
|
||||
key="update",
|
||||
name="Firmware",
|
||||
api_category=DATA_MACHINE_FIRMWARE_UPDATE_STATUS,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Set up WLED update based on a config entry."""
|
||||
data: RainMachineData = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
async_add_entities([RainMachineUpdateEntity(entry, data, UPDATE_DESCRIPTION)])
|
||||
|
||||
|
||||
class RainMachineUpdateEntity(RainMachineEntity, UpdateEntity):
|
||||
"""Define a RainMachine update entity."""
|
||||
|
||||
_attr_device_class = UpdateDeviceClass.FIRMWARE
|
||||
_attr_supported_features = (
|
||||
UpdateEntityFeature.INSTALL
|
||||
| UpdateEntityFeature.PROGRESS
|
||||
| UpdateEntityFeature.SPECIFIC_VERSION
|
||||
)
|
||||
|
||||
async def async_install(
|
||||
self, version: str | None, backup: bool, **kwargs: Any
|
||||
) -> None:
|
||||
"""Install an update."""
|
||||
try:
|
||||
await self._data.controller.machine.update_firmware()
|
||||
except RequestError as err:
|
||||
raise HomeAssistantError(f"Error while updating firmware: {err}") from err
|
||||
|
||||
await self.coordinator.async_refresh()
|
||||
|
||||
@callback
|
||||
def update_from_latest_data(self) -> None:
|
||||
"""Update the state."""
|
||||
if version := self._version_coordinator.data["swVer"]:
|
||||
self._attr_installed_version = version
|
||||
else:
|
||||
self._attr_installed_version = None
|
||||
|
||||
data = self.coordinator.data
|
||||
|
||||
if not data["update"]:
|
||||
self._attr_in_progress = False
|
||||
self._attr_latest_version = self._attr_installed_version
|
||||
return
|
||||
|
||||
self._attr_in_progress = UPDATE_STATE_MAP[data["updateStatus"]] in (
|
||||
UpdateStates.DOWNLOADING,
|
||||
UpdateStates.UPGRADING,
|
||||
UpdateStates.REBOOT,
|
||||
)
|
||||
self._attr_latest_version = data["packageDetails"]["newVersion"]
|
|
@ -41,6 +41,7 @@ def controller_fixture(
|
|||
controller_mac,
|
||||
data_api_versions,
|
||||
data_diagnostics_current,
|
||||
data_machine_firmare_update_status,
|
||||
data_programs,
|
||||
data_provision_settings,
|
||||
data_restrictions_current,
|
||||
|
@ -59,6 +60,9 @@ def controller_fixture(
|
|||
|
||||
controller.api.versions.return_value = data_api_versions
|
||||
controller.diagnostics.current.return_value = data_diagnostics_current
|
||||
controller.machine.get_firmware_update_status.return_value = (
|
||||
data_machine_firmare_update_status
|
||||
)
|
||||
controller.programs.all.return_value = data_programs
|
||||
controller.provisioning.settings.return_value = data_provision_settings
|
||||
controller.restrictions.current.return_value = data_restrictions_current
|
||||
|
@ -86,6 +90,14 @@ def data_diagnostics_current_fixture():
|
|||
return json.loads(load_fixture("diagnostics_current_data.json", "rainmachine"))
|
||||
|
||||
|
||||
@pytest.fixture(name="data_machine_firmare_update_status", scope="session")
|
||||
def data_machine_firmare_update_status_fixture():
|
||||
"""Define machine firmware update status data."""
|
||||
return json.loads(
|
||||
load_fixture("machine_firmware_update_status_data.json", "rainmachine")
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture(name="data_programs", scope="session")
|
||||
def data_programs_fixture():
|
||||
"""Define program data."""
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"lastUpdateCheckTimestamp": 1657825288,
|
||||
"packageDetails": [],
|
||||
"update": false,
|
||||
"lastUpdateCheck": "2022-07-14 13:01:28",
|
||||
"updateStatus": 1
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
"""Test RainMachine diagnostics."""
|
||||
from regenmaschine.errors import RainMachineError
|
||||
|
||||
from homeassistant.components.diagnostics import REDACTED
|
||||
|
||||
from tests.components.diagnostics import get_diagnostics_for_config_entry
|
||||
|
@ -19,89 +21,13 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach
|
|||
},
|
||||
"data": {
|
||||
"coordinator": {
|
||||
"provision.settings": {
|
||||
"system": {
|
||||
"httpEnabled": True,
|
||||
"rainSensorSnoozeDuration": 0,
|
||||
"uiUnitsMetric": False,
|
||||
"programZonesShowInactive": False,
|
||||
"programSingleSchedule": False,
|
||||
"standaloneMode": False,
|
||||
"masterValveAfter": 0,
|
||||
"touchSleepTimeout": 10,
|
||||
"selfTest": False,
|
||||
"useSoftwareRainSensor": False,
|
||||
"defaultZoneWateringDuration": 300,
|
||||
"maxLEDBrightness": 40,
|
||||
"simulatorHistorySize": 0,
|
||||
"vibration": False,
|
||||
"masterValveBefore": 0,
|
||||
"touchProgramToRun": None,
|
||||
"useRainSensor": False,
|
||||
"wizardHasRun": True,
|
||||
"waterLogHistorySize": 365,
|
||||
"netName": "Home",
|
||||
"softwareRainSensorMinQPF": 5,
|
||||
"touchAdvanced": False,
|
||||
"useBonjourService": True,
|
||||
"hardwareVersion": 3,
|
||||
"touchLongPressTimeout": 3,
|
||||
"showRestrictionsOnLed": False,
|
||||
"parserDataSizeInDays": 6,
|
||||
"programListShowInactive": True,
|
||||
"parserHistorySize": 365,
|
||||
"allowAlexaDiscovery": False,
|
||||
"automaticUpdates": True,
|
||||
"minLEDBrightness": 0,
|
||||
"minWateringDurationThreshold": 0,
|
||||
"localValveCount": 12,
|
||||
"touchAuthAPSeconds": 60,
|
||||
"useCommandLineArguments": False,
|
||||
"databasePath": "/rainmachine-app/DB/Default",
|
||||
"touchCyclePrograms": True,
|
||||
"zoneListShowInactive": True,
|
||||
"rainSensorRainStart": None,
|
||||
"zoneDuration": [
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
],
|
||||
"rainSensorIsNormallyClosed": True,
|
||||
"useCorrectionForPast": True,
|
||||
"useMasterValve": False,
|
||||
"runParsersBeforePrograms": True,
|
||||
"maxWateringCoef": 2,
|
||||
"mixerHistorySize": 365,
|
||||
},
|
||||
"location": {
|
||||
"elevation": REDACTED,
|
||||
"doyDownloaded": True,
|
||||
"zip": None,
|
||||
"windSensitivity": 0.5,
|
||||
"krs": 0.16,
|
||||
"stationID": REDACTED,
|
||||
"stationSource": REDACTED,
|
||||
"et0Average": 6.578,
|
||||
"latitude": REDACTED,
|
||||
"state": "Default",
|
||||
"stationName": REDACTED,
|
||||
"wsDays": 2,
|
||||
"stationDownloaded": True,
|
||||
"address": "Default",
|
||||
"rainSensitivity": 0.8,
|
||||
"timezone": REDACTED,
|
||||
"longitude": REDACTED,
|
||||
"name": "Home",
|
||||
},
|
||||
"api.versions": {"apiVer": "4.6.1", "hwVer": 3, "swVer": "4.0.1144"},
|
||||
"machine.firmware_update_status": {
|
||||
"lastUpdateCheckTimestamp": 1657825288,
|
||||
"packageDetails": [],
|
||||
"update": False,
|
||||
"lastUpdateCheck": "2022-07-14 13:01:28",
|
||||
"updateStatus": 1,
|
||||
},
|
||||
"programs": [
|
||||
{
|
||||
|
@ -381,6 +307,90 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach
|
|||
],
|
||||
},
|
||||
],
|
||||
"provision.settings": {
|
||||
"system": {
|
||||
"httpEnabled": True,
|
||||
"rainSensorSnoozeDuration": 0,
|
||||
"uiUnitsMetric": False,
|
||||
"programZonesShowInactive": False,
|
||||
"programSingleSchedule": False,
|
||||
"standaloneMode": False,
|
||||
"masterValveAfter": 0,
|
||||
"touchSleepTimeout": 10,
|
||||
"selfTest": False,
|
||||
"useSoftwareRainSensor": False,
|
||||
"defaultZoneWateringDuration": 300,
|
||||
"maxLEDBrightness": 40,
|
||||
"simulatorHistorySize": 0,
|
||||
"vibration": False,
|
||||
"masterValveBefore": 0,
|
||||
"touchProgramToRun": None,
|
||||
"useRainSensor": False,
|
||||
"wizardHasRun": True,
|
||||
"waterLogHistorySize": 365,
|
||||
"netName": "Home",
|
||||
"softwareRainSensorMinQPF": 5,
|
||||
"touchAdvanced": False,
|
||||
"useBonjourService": True,
|
||||
"hardwareVersion": 3,
|
||||
"touchLongPressTimeout": 3,
|
||||
"showRestrictionsOnLed": False,
|
||||
"parserDataSizeInDays": 6,
|
||||
"programListShowInactive": True,
|
||||
"parserHistorySize": 365,
|
||||
"allowAlexaDiscovery": False,
|
||||
"automaticUpdates": True,
|
||||
"minLEDBrightness": 0,
|
||||
"minWateringDurationThreshold": 0,
|
||||
"localValveCount": 12,
|
||||
"touchAuthAPSeconds": 60,
|
||||
"useCommandLineArguments": False,
|
||||
"databasePath": "/rainmachine-app/DB/Default",
|
||||
"touchCyclePrograms": True,
|
||||
"zoneListShowInactive": True,
|
||||
"rainSensorRainStart": None,
|
||||
"zoneDuration": [
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
],
|
||||
"rainSensorIsNormallyClosed": True,
|
||||
"useCorrectionForPast": True,
|
||||
"useMasterValve": False,
|
||||
"runParsersBeforePrograms": True,
|
||||
"maxWateringCoef": 2,
|
||||
"mixerHistorySize": 365,
|
||||
},
|
||||
"location": {
|
||||
"elevation": REDACTED,
|
||||
"doyDownloaded": True,
|
||||
"zip": None,
|
||||
"windSensitivity": 0.5,
|
||||
"krs": 0.16,
|
||||
"stationID": REDACTED,
|
||||
"stationSource": REDACTED,
|
||||
"et0Average": 6.578,
|
||||
"latitude": REDACTED,
|
||||
"state": "Default",
|
||||
"stationName": REDACTED,
|
||||
"wsDays": 2,
|
||||
"stationDownloaded": True,
|
||||
"address": "Default",
|
||||
"rainSensitivity": 0.8,
|
||||
"timezone": REDACTED,
|
||||
"longitude": REDACTED,
|
||||
"name": "Home",
|
||||
},
|
||||
},
|
||||
"restrictions.current": {
|
||||
"hourly": False,
|
||||
"freeze": False,
|
||||
|
@ -582,13 +592,7 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach
|
|||
},
|
||||
],
|
||||
},
|
||||
"controller": {
|
||||
"versions": {
|
||||
"apiVer": "4.6.1",
|
||||
"hwVer": 3,
|
||||
"swVer": "4.0.1144",
|
||||
},
|
||||
"current_diagnostics": {
|
||||
"controller_diagnostics": {
|
||||
"hasWifi": True,
|
||||
"uptime": "3 days, 18:14:14",
|
||||
"uptimeSeconds": 324854,
|
||||
|
@ -610,5 +614,598 @@ async def test_entry_diagnostics(hass, config_entry, hass_client, setup_rainmach
|
|||
"weatherStatus": True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
async def test_entry_diagnostics_failed_controller_diagnostics(
|
||||
hass, config_entry, controller, hass_client, setup_rainmachine
|
||||
):
|
||||
"""Test config entry diagnostics when the controller diagnostics API call fails."""
|
||||
controller.diagnostics.current.side_effect = RainMachineError
|
||||
assert await get_diagnostics_for_config_entry(hass, hass_client, config_entry) == {
|
||||
"entry": {
|
||||
"title": "Mock Title",
|
||||
"data": {
|
||||
"ip_address": "192.168.1.100",
|
||||
"password": REDACTED,
|
||||
"port": 8080,
|
||||
"ssl": True,
|
||||
},
|
||||
"options": {},
|
||||
},
|
||||
"data": {
|
||||
"coordinator": {
|
||||
"api.versions": {"apiVer": "4.6.1", "hwVer": 3, "swVer": "4.0.1144"},
|
||||
"machine.firmware_update_status": {
|
||||
"lastUpdateCheckTimestamp": 1657825288,
|
||||
"packageDetails": [],
|
||||
"update": False,
|
||||
"lastUpdateCheck": "2022-07-14 13:01:28",
|
||||
"updateStatus": 1,
|
||||
},
|
||||
"programs": [
|
||||
{
|
||||
"uid": 1,
|
||||
"name": "Morning",
|
||||
"active": True,
|
||||
"startTime": "06:00",
|
||||
"cycles": 0,
|
||||
"soak": 0,
|
||||
"cs_on": False,
|
||||
"delay": 0,
|
||||
"delay_on": False,
|
||||
"status": 0,
|
||||
"startTimeParams": {
|
||||
"offsetSign": 0,
|
||||
"type": 0,
|
||||
"offsetMinutes": 0,
|
||||
},
|
||||
"frequency": {"type": 0, "param": "0"},
|
||||
"coef": 0,
|
||||
"ignoreInternetWeather": False,
|
||||
"futureField1": 0,
|
||||
"freq_modified": 0,
|
||||
"useWaterSense": False,
|
||||
"nextRun": "2018-06-04",
|
||||
"startDate": "2018-04-28",
|
||||
"endDate": None,
|
||||
"yearlyRecurring": True,
|
||||
"simulationExpired": False,
|
||||
"wateringTimes": [
|
||||
{
|
||||
"id": 1,
|
||||
"order": -1,
|
||||
"name": "Landscaping",
|
||||
"duration": 0,
|
||||
"active": True,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"order": -1,
|
||||
"name": "Flower Box",
|
||||
"duration": 0,
|
||||
"active": True,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"order": -1,
|
||||
"name": "TEST",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"order": -1,
|
||||
"name": "Zone 4",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"order": -1,
|
||||
"name": "Zone 5",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"order": -1,
|
||||
"name": "Zone 6",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"order": -1,
|
||||
"name": "Zone 7",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"order": -1,
|
||||
"name": "Zone 8",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"order": -1,
|
||||
"name": "Zone 9",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"order": -1,
|
||||
"name": "Zone 10",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"order": -1,
|
||||
"name": "Zone 11",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"order": -1,
|
||||
"name": "Zone 12",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"uid": 2,
|
||||
"name": "Evening",
|
||||
"active": False,
|
||||
"startTime": "06:00",
|
||||
"cycles": 0,
|
||||
"soak": 0,
|
||||
"cs_on": False,
|
||||
"delay": 0,
|
||||
"delay_on": False,
|
||||
"status": 0,
|
||||
"startTimeParams": {
|
||||
"offsetSign": 0,
|
||||
"type": 0,
|
||||
"offsetMinutes": 0,
|
||||
},
|
||||
"frequency": {"type": 0, "param": "0"},
|
||||
"coef": 0,
|
||||
"ignoreInternetWeather": False,
|
||||
"futureField1": 0,
|
||||
"freq_modified": 0,
|
||||
"useWaterSense": False,
|
||||
"nextRun": "2018-06-04",
|
||||
"startDate": "2018-04-28",
|
||||
"endDate": None,
|
||||
"yearlyRecurring": True,
|
||||
"simulationExpired": False,
|
||||
"wateringTimes": [
|
||||
{
|
||||
"id": 1,
|
||||
"order": -1,
|
||||
"name": "Landscaping",
|
||||
"duration": 0,
|
||||
"active": True,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"order": -1,
|
||||
"name": "Flower Box",
|
||||
"duration": 0,
|
||||
"active": True,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"order": -1,
|
||||
"name": "TEST",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"order": -1,
|
||||
"name": "Zone 4",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"order": -1,
|
||||
"name": "Zone 5",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"order": -1,
|
||||
"name": "Zone 6",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"order": -1,
|
||||
"name": "Zone 7",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"order": -1,
|
||||
"name": "Zone 8",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"order": -1,
|
||||
"name": "Zone 9",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"order": -1,
|
||||
"name": "Zone 10",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"order": -1,
|
||||
"name": "Zone 11",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"order": -1,
|
||||
"name": "Zone 12",
|
||||
"duration": 0,
|
||||
"active": False,
|
||||
"userPercentage": 1,
|
||||
"minRuntimeCoef": 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"provision.settings": {
|
||||
"system": {
|
||||
"httpEnabled": True,
|
||||
"rainSensorSnoozeDuration": 0,
|
||||
"uiUnitsMetric": False,
|
||||
"programZonesShowInactive": False,
|
||||
"programSingleSchedule": False,
|
||||
"standaloneMode": False,
|
||||
"masterValveAfter": 0,
|
||||
"touchSleepTimeout": 10,
|
||||
"selfTest": False,
|
||||
"useSoftwareRainSensor": False,
|
||||
"defaultZoneWateringDuration": 300,
|
||||
"maxLEDBrightness": 40,
|
||||
"simulatorHistorySize": 0,
|
||||
"vibration": False,
|
||||
"masterValveBefore": 0,
|
||||
"touchProgramToRun": None,
|
||||
"useRainSensor": False,
|
||||
"wizardHasRun": True,
|
||||
"waterLogHistorySize": 365,
|
||||
"netName": "Home",
|
||||
"softwareRainSensorMinQPF": 5,
|
||||
"touchAdvanced": False,
|
||||
"useBonjourService": True,
|
||||
"hardwareVersion": 3,
|
||||
"touchLongPressTimeout": 3,
|
||||
"showRestrictionsOnLed": False,
|
||||
"parserDataSizeInDays": 6,
|
||||
"programListShowInactive": True,
|
||||
"parserHistorySize": 365,
|
||||
"allowAlexaDiscovery": False,
|
||||
"automaticUpdates": True,
|
||||
"minLEDBrightness": 0,
|
||||
"minWateringDurationThreshold": 0,
|
||||
"localValveCount": 12,
|
||||
"touchAuthAPSeconds": 60,
|
||||
"useCommandLineArguments": False,
|
||||
"databasePath": "/rainmachine-app/DB/Default",
|
||||
"touchCyclePrograms": True,
|
||||
"zoneListShowInactive": True,
|
||||
"rainSensorRainStart": None,
|
||||
"zoneDuration": [
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
300,
|
||||
],
|
||||
"rainSensorIsNormallyClosed": True,
|
||||
"useCorrectionForPast": True,
|
||||
"useMasterValve": False,
|
||||
"runParsersBeforePrograms": True,
|
||||
"maxWateringCoef": 2,
|
||||
"mixerHistorySize": 365,
|
||||
},
|
||||
"location": {
|
||||
"elevation": REDACTED,
|
||||
"doyDownloaded": True,
|
||||
"zip": None,
|
||||
"windSensitivity": 0.5,
|
||||
"krs": 0.16,
|
||||
"stationID": REDACTED,
|
||||
"stationSource": REDACTED,
|
||||
"et0Average": 6.578,
|
||||
"latitude": REDACTED,
|
||||
"state": "Default",
|
||||
"stationName": REDACTED,
|
||||
"wsDays": 2,
|
||||
"stationDownloaded": True,
|
||||
"address": "Default",
|
||||
"rainSensitivity": 0.8,
|
||||
"timezone": REDACTED,
|
||||
"longitude": REDACTED,
|
||||
"name": "Home",
|
||||
},
|
||||
},
|
||||
"restrictions.current": {
|
||||
"hourly": False,
|
||||
"freeze": False,
|
||||
"month": False,
|
||||
"weekDay": False,
|
||||
"rainDelay": False,
|
||||
"rainDelayCounter": -1,
|
||||
"rainSensor": False,
|
||||
},
|
||||
"restrictions.universal": {
|
||||
"hotDaysExtraWatering": False,
|
||||
"freezeProtectEnabled": True,
|
||||
"freezeProtectTemp": 2,
|
||||
"noWaterInWeekDays": "0000000",
|
||||
"noWaterInMonths": "000000000000",
|
||||
"rainDelayStartTime": 1524854551,
|
||||
"rainDelayDuration": 0,
|
||||
},
|
||||
"zones": [
|
||||
{
|
||||
"uid": 1,
|
||||
"name": "Landscaping",
|
||||
"state": 0,
|
||||
"active": True,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 4,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 2,
|
||||
"name": "Flower Box",
|
||||
"state": 0,
|
||||
"active": True,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 5,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 3,
|
||||
"name": "TEST",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 9,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 4,
|
||||
"name": "Zone 4",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 5,
|
||||
"name": "Zone 5",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 6,
|
||||
"name": "Zone 6",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 7,
|
||||
"name": "Zone 7",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 8,
|
||||
"name": "Zone 8",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 9,
|
||||
"name": "Zone 9",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 10,
|
||||
"name": "Zone 10",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 11,
|
||||
"name": "Zone 11",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
{
|
||||
"uid": 12,
|
||||
"name": "Zone 12",
|
||||
"state": 0,
|
||||
"active": False,
|
||||
"userDuration": 0,
|
||||
"machineDuration": 0,
|
||||
"remaining": 0,
|
||||
"cycle": 0,
|
||||
"noOfCycles": 0,
|
||||
"restriction": False,
|
||||
"type": 2,
|
||||
"master": False,
|
||||
"waterSense": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
"controller_diagnostics": None,
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue