add ha integration and added entity state api endpoint
This commit is contained in:
parent
249b111e67
commit
932168125c
10
home_assistant_integration/__init__.py
Normal file
10
home_assistant_integration/__init__.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
DOMAIN = "atc_mi_thermometer_gateway"
|
||||||
|
|
||||||
|
from .discover_gateways import start_discovery_client
|
||||||
|
|
||||||
|
|
||||||
|
def setup(hass, config):
|
||||||
|
hass.states.set("hello_state.world", "Paulus")
|
||||||
|
|
||||||
|
# Return boolean to indicate that initialization was successful.
|
||||||
|
return True
|
||||||
0
home_assistant_integration/api.py
Normal file
0
home_assistant_integration/api.py
Normal file
49
home_assistant_integration/discover_gateways.py
Normal file
49
home_assistant_integration/discover_gateways.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
from time import time
|
||||||
|
from socket import socket
|
||||||
|
from socket import AF_INET
|
||||||
|
from socket import SOCK_DGRAM
|
||||||
|
from socket import IPPROTO_UDP
|
||||||
|
from socket import SOL_SOCKET
|
||||||
|
from socket import SO_REUSEADDR
|
||||||
|
from socket import SO_BROADCAST
|
||||||
|
|
||||||
|
|
||||||
|
DISCOVERY_ACK = 'IP_DISCOVERY_ACK'.encode() # ACK for broadcast
|
||||||
|
DISCOVERY_OK = 'IP_DISCOVERY_OK'.encode() # Not used yet
|
||||||
|
DISCOVERY_RSP_GTW = 'IP_DISCOVERY_RSP_GTW'.encode() # RSP for gateway
|
||||||
|
DISCOVERY_RSP_MSH = 'IP_DISCOVERY_RSP_MSH'.encode() # RSP for mesh
|
||||||
|
DISCOVERY_TIMEOUT = 0.5
|
||||||
|
SOCKET_TIMEOUT = 0.2
|
||||||
|
PORT_SERVER = 9434
|
||||||
|
PORT_CLIENT = 9435
|
||||||
|
|
||||||
|
|
||||||
|
def start_discovery_client():
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||||
|
sock.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
|
sock.settimeout(SOCKET_TIMEOUT)
|
||||||
|
server_address = ('255.255.255.255', PORT_SERVER)
|
||||||
|
start_time_stamp = time()
|
||||||
|
delta = round(time() - start_time_stamp, 2)
|
||||||
|
discovered_devices = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
sock.bind(('', PORT_CLIENT))
|
||||||
|
|
||||||
|
while delta <= DISCOVERY_TIMEOUT:
|
||||||
|
delta = round(time() - start_time_stamp, 2)
|
||||||
|
sock.sendto(DISCOVERY_ACK, server_address)
|
||||||
|
data, addr = sock.recvfrom(4096)
|
||||||
|
|
||||||
|
if str(addr[0]) in discovered_devices: continue
|
||||||
|
if data == DISCOVERY_RSP_GTW:
|
||||||
|
discovered_devices.append(str(addr[0]))
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
print(err)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
sock.close()
|
||||||
|
return discovered_devices[0]
|
||||||
|
|
||||||
51
home_assistant_integration/sensor.py
Normal file
51
home_assistant_integration/sensor.py
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
"""Platform for light integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from .discover_gateways import start_discovery_client
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from pprint import pformat
|
||||||
|
|
||||||
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
|
from homeassistant.components.sensor import SensorEntity
|
||||||
|
from homeassistant.const import CONF_NAME, CONF_MAC
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
from homeassistant.helpers.typing import DiscoveryInfoType
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger("atc_mi_thermometer_gateway")
|
||||||
|
|
||||||
|
|
||||||
|
def setup_platform(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigType,
|
||||||
|
add_entities: AddEntitiesCallback,
|
||||||
|
discovery_info: DiscoveryInfoType | None = None):
|
||||||
|
|
||||||
|
_LOGGER.info(pformat(config))
|
||||||
|
gateway = start_discovery_client()
|
||||||
|
|
||||||
|
add_entities([Gateway(ip=gateway[0])])
|
||||||
|
|
||||||
|
|
||||||
|
class Gateway(SensorEntity):
|
||||||
|
def __init__(self, ip:str):
|
||||||
|
self._ip = ip
|
||||||
|
self._online = False
|
||||||
|
self._discovered_devices = []
|
||||||
|
|
||||||
|
@property
|
||||||
|
def ip(self):
|
||||||
|
return self._ip
|
||||||
|
|
||||||
|
@property
|
||||||
|
def online(self):
|
||||||
|
return self._online
|
||||||
|
|
||||||
|
@property
|
||||||
|
def discovered_devices(self):
|
||||||
|
return self._discovered_devices
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
import json
|
||||||
import os
|
import os
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask import jsonify
|
from flask import jsonify
|
||||||
@ -6,6 +7,8 @@ from flask_cors import CORS
|
|||||||
from flask_cors import cross_origin
|
from flask_cors import cross_origin
|
||||||
from check_update import check_for_update
|
from check_update import check_for_update
|
||||||
|
|
||||||
|
from data_class import LogEntry
|
||||||
|
|
||||||
|
|
||||||
class API:
|
class API:
|
||||||
"""
|
"""
|
||||||
@ -48,6 +51,15 @@ class API:
|
|||||||
workdir, filename = os.path.split(os.path.abspath(__file__))
|
workdir, filename = os.path.split(os.path.abspath(__file__))
|
||||||
return send_from_directory(f'{workdir}/data', path)
|
return send_from_directory(f'{workdir}/data', path)
|
||||||
|
|
||||||
|
@self.app.route('/api/state/<path:path>')
|
||||||
|
@cross_origin()
|
||||||
|
def serve_entity_state(path):
|
||||||
|
workdir, filename = os.path.split(os.path.abspath(__file__))
|
||||||
|
state = json.load(open(f'{workdir}/data/{path}', mode='r'))
|
||||||
|
print(state['measurements'])
|
||||||
|
entity_state = LogEntry(data=state)
|
||||||
|
return jsonify(entity_state.to_json())
|
||||||
|
|
||||||
@self.app.route('/charts')
|
@self.app.route('/charts')
|
||||||
@cross_origin()
|
@cross_origin()
|
||||||
def serve_index():
|
def serve_index():
|
||||||
|
|||||||
@ -37,3 +37,28 @@ class Data:
|
|||||||
"battery_volt": self.battery_volt,
|
"battery_volt": self.battery_volt,
|
||||||
"count": self.count,
|
"count": self.count,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class LogEntry:
|
||||||
|
def __init__(self, data):
|
||||||
|
self.name = data['name']
|
||||||
|
self.room = data['room']
|
||||||
|
self.timestamp = data['measurements'][:-1]['timestamp']
|
||||||
|
self.temperature = data['measurements'][:-1]['temperature']
|
||||||
|
self.humidity = data['measurements'][:-1]['humidity']
|
||||||
|
self.battery_percent = data['measurements'][:-1]['battery_percent']
|
||||||
|
self.battery_volt = data['measurements'][:-1]['battery_volt']
|
||||||
|
self.rssi = data['measurements'][:-1]['rssi']
|
||||||
|
|
||||||
|
def to_json(self):
|
||||||
|
return {
|
||||||
|
"name": self.name,
|
||||||
|
"room": self.room,
|
||||||
|
"timestamp": self.timestamp,
|
||||||
|
"temperature": self.temperature,
|
||||||
|
"humidity": self.humidity,
|
||||||
|
"battery_percent": self.battery_percent,
|
||||||
|
"battery_volt": self.battery_volt,
|
||||||
|
"rssi": self.rssi
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user