Skip to content

Commit

Permalink
feat: Add Vitoconnect Opto 2 / Heatbox2 as gateway (#24) (#408)
Browse files Browse the repository at this point in the history
feat: add Vitoconnect Opto 2 / Heatbox2 as gateway (#24)

* add Vitoconnect Opto 2 / Heatbox2 as gateway

* add AutoDetect test

* update tests

* Update PyViCareService.py remove empty lines

* Fix Pylint issue with docstring

* remove .pylintrc file

Co-authored-by: Tobin Rosenau <[email protected]>
  • Loading branch information
CFenner and Nibot1 authored Sep 26, 2024
1 parent ed9ccec commit 2c941ba
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 8 deletions.
3 changes: 2 additions & 1 deletion PyViCare/PyViCareDeviceConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ def asAutoDetectDevice(self):
(self.asGateway, r"E3_TCU10_x07", ["type:gateway;TCU300"]),
(self.asElectricalEnergySystem, r"E3_VitoCharge_03", ["type:ees"]),
(self.asVentilation, r"E3_ViAir", ["type:ventilation"]),
(self.asGateway, r"Heatbox1", ["type:gateway;VitoconnectOpto1"])
(self.asGateway, r"Heatbox1", ["type:gateway;VitoconnectOpto1"]),
(self.asGateway, r"Heatbox2", ["type:gateway;VitoconnectOpto2/OT2"])
]

for (creator_method, type_name, roles) in device_types:
Expand Down
8 changes: 1 addition & 7 deletions PyViCare/PyViCareService.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
logger = logging.getLogger('ViCare')
logger.addHandler(logging.NullHandler())


def readFeature(entities, property_name):
feature = next(
(f for f in entities if f["feature"] == property_name), None)
Expand All @@ -18,22 +17,18 @@ def readFeature(entities, property_name):

return feature


def hasRoles(requested_roles: List[str], existing_roles: List[str]) -> bool:
return len(requested_roles) > 0 and set(requested_roles).issubset(set(existing_roles))


def buildSetPropertyUrl(accessor, property_name, action):
return f'/features/installations/{accessor.id}/gateways/{accessor.serial}/devices/{accessor.device_id}/features/{property_name}/commands/{action}'


class ViCareDeviceAccessor:
def __init__(self, _id: int, serial: str, device_id: str) -> None:
self.id = _id
self.serial = serial
self.device_id = device_id


class ViCareService:
def __init__(self, oauth_manager: AbstractViCareOAuthManager, accessor: ViCareDeviceAccessor, roles: List[str]) -> None:
self.oauth_manager = oauth_manager
Expand All @@ -49,12 +44,11 @@ def buildGetPropertyUrl(self, property_name):
return f'/features/installations/{self.accessor.id}/gateways/{self.accessor.serial}/features/{property_name}'
return f'/features/installations/{self.accessor.id}/gateways/{self.accessor.serial}/devices/{self.accessor.device_id}/features/{property_name}'


def hasRoles(self, requested_roles) -> bool:
return hasRoles(requested_roles, self.roles)

def _isGateway(self) -> bool:
return self.hasRoles(["type:gateway;VitoconnectOpto1"]) or self.hasRoles(["type:gateway;TCU300"])
return self.hasRoles(["type:gateway;VitoconnectOpto1"]) or self.hasRoles(["type:gateway;VitoconnectOpto2/OT2"]) or self.hasRoles(["type:gateway;TCU300"])

def setProperty(self, property_name: str, action: str, data: Any) -> Any:
url = buildSetPropertyUrl(
Expand Down
97 changes: 97 additions & 0 deletions tests/response/VitoconnectOpto2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
{
"data": [
{
"feature": "gateway.devices",
"gatewayId": "##############",
"timestamp": "2024-03-28T05:06:02.633Z",
"isEnabled": true,
"isReady": true,
"apiVersion": 1,
"uri": "https://api.viessmann.com/iot/v1/features/installations/######/gateways/##############/features/gateway.devices",
"properties": {
"devices": {
"type": "DeviceList",
"value": [
{
"id": "gateway",
"fingerprint": "###",
"modelId": "Heatbox2_SRC",
"modelVersion": "###",
"name": "Heatbox 2 SRC, Vitoconnect",
"type": "vitoconnect",
"roles": [
"type:gateway;VitoconnectOpto2/OT2",
"type:hb2",
"type:legacy"
],
"status": "online"
},
{
"id": "0",
"fingerprint": "###",
"modelId": "VPlusHO1_40",
"modelVersion": "###",
"name": "VT 200 (HO1A / HO1B)",
"type": "heating",
"roles": [
"type:boiler",
"type:legacy",
"type:product;VPlusHO1"
],
"status": "online"
},
{
"id": "RoomControl-1",
"fingerprint": "###",
"modelId": "Smart_RoomControl",
"modelVersion": "###",
"name": "Smart_RoomControl_49",
"type": "roomControl",
"roles": [
"capability:monetization;FTDC",
"capability:monetization;OWD",
"capability:zigbeeCoordinator",
"type:legacy",
"type:virtual;smartRoomControl"
],
"status": "online"
},
{
"id": "zigbee-#####",
"fingerprint": "###",
"modelId": "Smart_Device_eTRV_generic_50",
"modelVersion": "ac746d50a111d3eb8fa54146c05971aa2bc5b5cc",
"name": "Smart_Device_eTRV_generic_50",
"type": "zigbee",
"roles": [
"type:actuator",
"type:legacy",
"type:radiator",
"type:smartRoomDevice"
],
"status": "online"
}
]
}
},
"commands": {}
},
{
"feature": "gateway.wifi",
"gatewayId": "##############",
"timestamp": "2024-03-30T17:31:57.758Z",
"isEnabled": true,
"isReady": true,
"apiVersion": 1,
"uri": "https://api.viessmann.com/iot/v1/features/installations/######/gateways/##############/features/gateway.wifi",
"properties": {
"strength": {
"type": "number",
"value": -41,
"unit": ""
}
},
"commands": {}
}
]
}
11 changes: 11 additions & 0 deletions tests/test_PyViCareDeviceConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,11 @@ def test_autoDetect_VitoconnectOpto1_asGateway(self):
device_type = c.asAutoDetectDevice()
self.assertEqual("Gateway", type(device_type).__name__)

def test_autoDetect_VitoconnectOpto2_asGateway(self):
c = PyViCareDeviceConfig(self.service, "0", "Heatbox2_SRC", "Online")
device_type = c.asAutoDetectDevice()
self.assertEqual("Gateway", type(device_type).__name__)

def test_autoDetect_TCU300_asGateway(self):
c = PyViCareDeviceConfig(self.service, "0", "E3_TCU10_x07", "Online")
device_type = c.asAutoDetectDevice()
Expand All @@ -83,6 +88,12 @@ def test_autoDetect_RoleGateway_asGateway(self):
device_type = c.asAutoDetectDevice()
self.assertEqual("Gateway", type(device_type).__name__)

def test_autoDetect_RoleGateway_asGateway_vc_opto2(self):
self.service.hasRoles = has_roles(["type:gateway;VitoconnectOpto2/OT2"])
c = PyViCareDeviceConfig(self.service, "0", "Unknown", "Online")
device_type = c.asAutoDetectDevice()
self.assertEqual("Gateway", type(device_type).__name__)

def test_autoDetect_RoleGateway_asGateway_TCU300(self):
self.service.hasRoles = has_roles(["type:gateway;TCU300"])
c = PyViCareDeviceConfig(self.service, "0", "Unknown", "Online")
Expand Down
18 changes: 18 additions & 0 deletions tests/test_VitoconnectOpto2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import unittest

from PyViCare.PyViCareGateway import Gateway
from tests.ViCareServiceMock import ViCareServiceMock


class VitoconnectOpto2(unittest.TestCase):
def setUp(self):
self.service = ViCareServiceMock('response/VitoconnectOpto2.json')
self.device = Gateway(self.service)

def test_getSerial(self):
self.assertEqual(
self.device.getSerial(), "##############")

def test_getWifiSignalStrength(self):
self.assertEqual(
self.device.getWifiSignalStrength(), -41)

0 comments on commit 2c941ba

Please sign in to comment.