1 """Support for SNMP enabled switch."""
3 from __future__
import annotations
8 import pysnmp.hlapi.asyncio
as hlapi
9 from pysnmp.hlapi.asyncio
import (
18 from pysnmp.proto.rfc1902
import (
32 import voluptuous
as vol
35 PLATFORM_SCHEMA
as SWITCH_PLATFORM_SCHEMA,
60 DEFAULT_AUTH_PROTOCOL,
64 DEFAULT_PRIV_PROTOCOL,
74 async_create_command_cmd_args,
75 async_create_request_cmd_args,
78 _LOGGER = logging.getLogger(__name__)
80 CONF_COMMAND_OID =
"command_oid"
81 CONF_COMMAND_PAYLOAD_OFF =
"command_payload_off"
82 CONF_COMMAND_PAYLOAD_ON =
"command_payload_on"
84 DEFAULT_COMMUNITY =
"private"
85 DEFAULT_PAYLOAD_OFF = 0
86 DEFAULT_PAYLOAD_ON = 1
89 "Counter32": Counter32,
90 "Counter64": Counter64,
92 "Integer32": Integer32,
94 "IpAddress": IpAddress,
97 "ObjectIdentifier": ObjectIdentifier,
98 "OctetString": OctetString,
100 "TimeTicks": TimeTicks,
101 "Unsigned32": Unsigned32,
104 PLATFORM_SCHEMA = SWITCH_PLATFORM_SCHEMA.extend(
106 vol.Required(CONF_BASEOID): cv.string,
107 vol.Optional(CONF_COMMAND_OID): cv.string,
108 vol.Optional(CONF_COMMAND_PAYLOAD_ON): cv.string,
109 vol.Optional(CONF_COMMAND_PAYLOAD_OFF): cv.string,
110 vol.Optional(CONF_COMMUNITY, default=DEFAULT_COMMUNITY): cv.string,
111 vol.Optional(CONF_HOST, default=DEFAULT_HOST): cv.string,
112 vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
113 vol.Optional(CONF_PAYLOAD_OFF, default=DEFAULT_PAYLOAD_OFF): cv.string,
114 vol.Optional(CONF_PAYLOAD_ON, default=DEFAULT_PAYLOAD_ON): cv.string,
115 vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
116 vol.Optional(CONF_VERSION, default=DEFAULT_VERSION): vol.In(SNMP_VERSIONS),
117 vol.Optional(CONF_USERNAME): cv.string,
118 vol.Optional(CONF_AUTH_KEY): cv.string,
119 vol.Optional(CONF_AUTH_PROTOCOL, default=DEFAULT_AUTH_PROTOCOL): vol.In(
122 vol.Optional(CONF_PRIV_KEY): cv.string,
123 vol.Optional(CONF_PRIV_PROTOCOL, default=DEFAULT_PRIV_PROTOCOL): vol.In(
126 vol.Optional(CONF_VARTYPE, default=DEFAULT_VARTYPE): cv.string,
134 async_add_entities: AddEntitiesCallback,
135 discovery_info: DiscoveryInfoType |
None =
None,
137 """Set up the SNMP switch."""
138 name: str = config[CONF_NAME]
139 host: str = config[CONF_HOST]
140 port: int = config[CONF_PORT]
141 community = config.get(CONF_COMMUNITY)
142 baseoid: str = config[CONF_BASEOID]
143 command_oid: str |
None = config.get(CONF_COMMAND_OID)
144 command_payload_on: str |
None = config.get(CONF_COMMAND_PAYLOAD_ON)
145 command_payload_off: str |
None = config.get(CONF_COMMAND_PAYLOAD_OFF)
146 version: str = config[CONF_VERSION]
147 username = config.get(CONF_USERNAME)
148 authkey = config.get(CONF_AUTH_KEY)
149 authproto: str = config[CONF_AUTH_PROTOCOL]
150 privkey = config.get(CONF_PRIV_KEY)
151 privproto: str = config[CONF_PRIV_PROTOCOL]
152 payload_on: str = config[CONF_PAYLOAD_ON]
153 payload_off: str = config[CONF_PAYLOAD_OFF]
154 vartype: str = config[CONF_VARTYPE]
162 auth_data = UsmUserData(
164 authKey=authkey
or None,
165 privKey=privkey
or None,
166 authProtocol=getattr(hlapi, MAP_AUTH_PROTOCOLS[authproto]),
167 privProtocol=getattr(hlapi, MAP_PRIV_PROTOCOLS[privproto]),
170 auth_data = CommunityData(community, mpModel=SNMP_VERSIONS[version])
172 transport = UdpTransportTarget((host, port))
174 hass, auth_data, transport, baseoid
200 """Representation of a SNMP switch."""
208 commandoid: str |
None,
211 command_payload_on: str |
None,
212 command_payload_off: str |
None,
214 request_args: RequestArgsType,
215 command_args: CommandArgsType,
217 """Initialize the switch."""
228 self.
_state_state: bool |
None =
None
231 self.
_target_target = UdpTransportTarget((host, port))
236 """Turn on the switch."""
241 """Turn off the switch."""
247 await self.
_set_set(command)
249 elif self.
_vartype_vartype ==
"Null":
250 await self.
_set_set(
"")
254 await self.
_set_set(MAP_SNMP_VARTYPES.get(self.
_vartype_vartype, Integer)(command))
257 """Update the state."""
259 errindication, errstatus, errindex, restable = get_result
262 _LOGGER.error(
"SNMP error: %s", errindication)
265 "SNMP error: %s at %s",
266 errstatus.prettyPrint(),
267 errindex
and restable[-1][
int(errindex) - 1]
or "?",
270 for resrow
in restable:
271 if resrow[-1] == self.
_payload_on_payload_on
or resrow[-1] == Integer(
275 elif resrow[-1] == self.
_payload_off_payload_off
or resrow[-1] == Integer(
281 "Invalid payload '%s' received for entity %s, state is unknown",
289 """Return true if switch is on; False if off. None if unknown."""
292 async
def _set(self, value: Any) ->
None:
293 """Set the state of the switch."""
None async_turn_on(self, **Any kwargs)
None async_turn_off(self, **Any kwargs)
None __init__(self, str name, str host, int port, str baseoid, str|None commandoid, str payload_on, str payload_off, str|None command_payload_on, str|None command_payload_off, str vartype, RequestArgsType request_args, CommandArgsType command_args)
None _set(self, Any value)
None _execute_command(self, str command)
None async_setup_platform(HomeAssistant hass, ConfigType config, AddEntitiesCallback async_add_entities, DiscoveryInfoType|None discovery_info=None)
RequestArgsType async_create_request_cmd_args(HomeAssistant hass, UsmUserData|CommunityData auth_data, UdpTransportTarget|Udp6TransportTarget target, str object_id)
CommandArgsType async_create_command_cmd_args(HomeAssistant hass, UsmUserData|CommunityData auth_data, UdpTransportTarget|Udp6TransportTarget target)