Skip to content

Commit

Permalink
Merge pull request #1 from JohNan/johnan/network-info
Browse files Browse the repository at this point in the history
Adds network info and fixes error with multiple event in same payload
  • Loading branch information
JohNan authored Sep 19, 2023
2 parents 7009a43 + f35d4dc commit bf338d8
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 31 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,3 +141,5 @@ dmypy.json
# Pyre type checker
.pyre/
/.tool-versions

/pyflichub/version.py
11 changes: 9 additions & 2 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
from pyflichub.client import FlicHubTcpClient
from pyflichub.command import Command
from pyflichub.event import Event
from pyflichub.network import Network

logging.basicConfig(level=logging.DEBUG)

CLIENT_READY_TIMEOUT = 10.0
HOST = ('192.168.1.64', 8124)
HOST = ('192.168.1.249', 8124)


def event_callback(button: FlicButton, event: Event):
Expand Down Expand Up @@ -45,10 +46,16 @@ def client_disconnected():
print(f"Client not connected after {CLIENT_READY_TIMEOUT} secs so terminating")
exit()

buttons = await client.get_buttons()
buttons: [FlicButton] = await client.get_buttons()
for button in buttons:
print(f"Button name: {button.name} - Connected: {button.connected}")

network: Network = await client.get_network()
if network.has_wifi():
print(f"Wifi State: {network.wifi.state} - Connected: {network.wifi.connected}")
if network.has_ethernet():
print(f"Ethernet IP: {network.ethernet.ip} - Connected: {network.ethernet.connected}")

# for button in buttons:
# print(f"Button name: {button.name} - Battery: {await client.get_battery_status(button.bdaddr)}")

Expand Down
9 changes: 6 additions & 3 deletions pyflichub/button.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
class FlicButton(dict):
from datetime import datetime


class FlicButton():
def __init__(self, bdaddr: str, serial_number: str, color: str, name: str, active_disconnect: bool, connected: bool,
ready: bool, battery_status: int, uuid: str, flic_version: int, firmware_version: int, key: str,
passive_mode: bool) -> None:
super().__init__()
passive_mode: bool, battery_timestamp: datetime) -> None:
self.bdaddr = bdaddr
self.serial_number = serial_number
self.color = color
Expand All @@ -16,3 +18,4 @@ def __init__(self, bdaddr: str, serial_number: str, color: str, name: str, activ
self.firmware_version = firmware_version
self.key = key
self.passive_mode = passive_mode
self.battery_timestamp = battery_timestamp
50 changes: 39 additions & 11 deletions pyflichub/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import json
import logging
import time
from datetime import datetime
from functools import partial, wraps
from typing import Union

Expand All @@ -11,6 +12,7 @@
from pyflichub.command import Command
from pyflichub.event import Event
from pyflichub.button import FlicButton
from pyflichub.network import Network

_LOGGER = logging.getLogger(__name__)

Expand All @@ -30,6 +32,7 @@ async def run(*args, loop=None, executor=None, **kwargs):

class FlicHubTcpClient(asyncio.Protocol):
buttons: [FlicButton] = []
network: Network

def __init__(self, ip, port, loop, timeout=1.0, reconnect_timeout=10.0, event_callback=None, command_callback=None):
self._data_ready: Union[asyncio.Event, None] = None
Expand Down Expand Up @@ -89,6 +92,9 @@ async def connect(self):
async def get_buttons(self):
return await self._async_send_command('buttons')

async def get_network(self):
return await self._async_send_command('network')

async def get_battery_status(self, bdaddr: str):
return await self._async_send_command(f'battery;{bdaddr}')

Expand All @@ -113,18 +119,19 @@ def connection_made(self, transport):
def data_received(self, data):
decoded_data = data.decode()
_LOGGER.debug('Data received: {!r}'.format(decoded_data))
for data_part in [data_part for data_part in decoded_data.split("\n") if data_part.strip()]:
if data_part == 'pong':
pass

if decoded_data == 'pong':
return

try:
msg = json.loads(decoded_data)
if 'event' in msg:
self._handle_event(Event(**msg))
if 'command' in msg:
self._handle_command(Command(**msg))
except Exception:
_LOGGER.warning('Unable to decode received data')
try:
msg = json.loads(data_part, cls=_JSONDecoder)
if 'event' in msg:
self._handle_event(Event(**msg))
if 'command' in msg:
self._handle_command(Command(**msg))
except Exception as e:
_LOGGER.warning(e, exc_info = True)
_LOGGER.warning('Unable to decode received data')


def connection_lost(self, exc):
Expand All @@ -139,6 +146,13 @@ def _handle_command(self, cmd: Command):
command_data = cmd.data = self.buttons
for button in self.buttons:
_LOGGER.debug(f"Button name: {button.name} - Connected: {button.connected}")
if cmd.command == 'network':
self.network = Network(**humps.decamelize(cmd.data))
command_data = cmd.data = self.network
if self.network.has_wifi():
_LOGGER.debug(f"Wifi State: {self.network.wifi.state} - Connected: {self.network.wifi.connected}")
if self.network.has_ethernet():
_LOGGER.debug(f"Ethernet IP: {self.network.ethernet.ip} - Connected: {self.network.ethernet.connected}")

if self._data_ready is not None:
self._data_ready.set()
Expand Down Expand Up @@ -170,3 +184,17 @@ def _check_connection(self):
msg = ""
self._transport.write(msg.encode())
self._tcp_check_timer = time.time()

class _JSONDecoder(json.JSONDecoder):
def __init__(self, *args, **kwargs):
json.JSONDecoder.__init__(
self, object_hook=self.object_hook, *args, **kwargs)

def object_hook(self, obj):
ret = {}
for key, value in obj.items():
if key in {'batteryTimestamp'}:
ret[key] = datetime.fromtimestamp(value/1000)
else:
ret[key] = value
return ret
56 changes: 56 additions & 0 deletions pyflichub/network.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from typing import List


class WifiInfo:
state: str
ssid: str

def __init__(self, connected, ip, mac):
self.connected = connected
self.ip = ip
self.mac = mac


class EthernetInfo:
def __init__(self, connected, ip, mac):
self.connected = connected
self.ip = ip
self.mac = mac


class DhcpInfo:
def __init__(self, wifi=None, ethernet=None):
self.wifi = WifiInfo(**wifi) if wifi else None
self.ethernet = EthernetInfo(**ethernet) if ethernet else None


class _WifiState:
def __init__(self, state, ssid):
self.state = state
self.ssid = ssid


def _decode_ssid(ssid_list):
return ''.join(chr(byte) for byte in ssid_list)


class Network:
def __init__(self, dhcp, wifi_state=None):
self._dhcp = DhcpInfo(**dhcp)
self._dhcp.wifi.state = wifi_state.get('state', None) if wifi_state else None
self._dhcp.wifi.ssid = _decode_ssid(wifi_state.get('ssid', None)) if wifi_state else None

def has_wifi(self) -> bool:
return self._dhcp.wifi is not None

def has_ethernet(self) -> bool:
return self._dhcp.ethernet is not None

@property
def wifi(self) -> WifiInfo:
return self._dhcp.wifi

@property
def ethernet(self) -> EthernetInfo:
return self._dhcp.ethernet

40 changes: 25 additions & 15 deletions tcpserver.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
console.log("Made by JohNan - https://github.com/JohNan/pyflichub-tcpclient")

var network = require('network');
var net = require('net');
var buttons = require('buttons');
const EOL = "\n";

// Configuration - start
const PORT = 8124;
Expand All @@ -20,7 +22,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': ''
}
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};


Expand All @@ -31,7 +33,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': ''
}
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};

var buttonAddedHandler = function (button) {
Expand All @@ -41,7 +43,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': ''
}
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};

var buttonDownHandler = function (button) {
Expand All @@ -51,7 +53,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': 'down'
}
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};

var buttonUpHandler = function (button) {
Expand All @@ -61,7 +63,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': 'up'
}
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};

var buttonSingleOrDoubleClickOrHoldHandler = function (button) {
Expand All @@ -72,7 +74,7 @@ net.createServer(function (socket) {
'button': button.bdaddr,
'action': action
};
socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
};

function sendButtons() {
Expand All @@ -84,7 +86,8 @@ net.createServer(function (socket) {
'data': _buttons
};

socket.write(JSON.stringify(response))
console.log(response)
socket.write(JSON.stringify(response)+EOL)
}

buttons.on('buttonSingleOrDoubleClickOrHold', buttonSingleOrDoubleClickOrHoldHandler);
Expand Down Expand Up @@ -123,7 +126,7 @@ net.createServer(function (socket) {
'data': button.batteryStatus
};

socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
}

if (msg === "buttons") {
Expand All @@ -135,21 +138,28 @@ net.createServer(function (socket) {
'data': _buttons
};

socket.write(JSON.stringify(response))
socket.write(JSON.stringify(response)+EOL)
}

if (msg === "network") {
const _network = network.getState();
console.log(JSON.stringify(_network))

const response = {
'command': 'network',
'data': _network
};

socket.write(JSON.stringify(response)+EOL)
}

if (msg === "ping") {
socket.write("pong")
}
});

// Send current buttons every 10 seconds
refreshIntervalId = setInterval(sendButtons, 10000);
}).listen(PORT, function () {
console.log("Opened server on port: " + PORT);
});

console.log("The server should have started now!")
console.log("Waiting for connections...")


console.log("Waiting for connections...")

0 comments on commit bf338d8

Please sign in to comment.