Last active
January 27, 2019 16:35
-
-
Save radek-senfeld/5086fbc40cc86c06478be85c533a718a to your computer and use it in GitHub Desktop.
MySensors Ethernet Gateway Hub
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import asyncore | |
import optparse | |
import collections | |
# Config | |
GATEWAY_HOST = "your-gateway-hostname-or-ip" | |
GATEWAY_PORT = 5003 | |
GATEWAY_INIT = [ | |
bytes("\n", "ascii"), | |
] | |
SERVER_BACKLOG = 5 | |
# | |
class Gateway(asyncore.dispatcher): | |
def __init__(self, host, port): | |
asyncore.dispatcher.__init__(self) | |
self.buffer = collections.deque(GATEWAY_INIT) | |
self.clients = [] | |
self.create_socket() | |
self.connect((host, port)) | |
def add_client(self, client): | |
self.clients.append(client) | |
def remove_client(self, client): | |
try: | |
self.clients.remove(client) | |
except ValueError: | |
pass | |
def broadcast(self, message): | |
print("G -> C: {}". format(message)) | |
for client in self.clients: | |
client.enqueue(message) | |
def enqueue(self, message): | |
print("G <- C: {}". format(message)) | |
self.buffer.append(message) | |
def writable(self): | |
return len(self.buffer) > 0 | |
def handle_connect(self): | |
pass | |
def handle_close(self): | |
self.close() | |
def handle_read(self): | |
message = self.recv(1024) | |
if len(message) > 0: | |
self.broadcast(message) | |
def handle_write(self): | |
if len(self.buffer) > 0: | |
message = self.buffer.popleft() | |
sent = self.send(message) | |
if sent < len(message): | |
self.buffer.appendleft(message[sent:]) | |
class Client(asyncore.dispatcher): | |
def __init__(self, sock, hub): | |
asyncore.dispatcher.__init__(self, sock) | |
self.buffer = collections.deque() | |
self.hub = hub | |
def enqueue(self, message): | |
self.buffer.append(message) | |
def writable(self): | |
return len(self.buffer) > 0 | |
def handle_close(self): | |
self.hub.gateway.remove_client(self) | |
self.close() | |
def handle_read(self): | |
message = self.recv(1024) | |
if len(message) > 0: | |
self.hub.gateway.enqueue(message) | |
def handle_write(self): | |
if len(self.buffer) > 0: | |
message = self.buffer.popleft() | |
sent = self.send(message) | |
if sent < len(message): | |
self.buffer.appendleft(message[sent:]) | |
class Hub(asyncore.dispatcher): | |
def __init__(self, host, port, gateway): | |
asyncore.dispatcher.__init__(self) | |
self.gateway = gateway | |
self.create_socket() | |
self.set_reuse_addr() | |
self.bind((host, port)) | |
self.listen(SERVER_BACKLOG) | |
def handle_accepted(self, sock, addr): | |
client = Client(sock, self) | |
self.gateway.add_client(client) | |
if __name__ == "__main__": | |
parser = optparse.OptionParser() | |
parser.add_option("-l", "--listen", dest="host", default="0.0.0.0", help="Hostname or IP address. Default is 0.0.0.0") | |
parser.add_option("-p", "--port", dest="port", type="int", default=5003, help="Port. Default is 5003") | |
options, args = parser.parse_args() | |
gateway = Gateway(GATEWAY_HOST, GATEWAY_PORT) | |
hub = Hub(options.host, options.port, gateway) | |
asyncore.loop() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello everyone,
recently I've deployed MySensors Ethernet Gateway on an iTead's iBoard W5100 and got bit by the Arduino / MySensors limition - single connection to the gateway.
As I'm experimenting with Node-RED, Domoticz and might be adding HomeAssistant to the mix, I tried really hard to find a working solution to this situation and failed.
Arduino and MySensors could be fixed to support up to 4 connections but in the end I decided to solve the problem by a simple Python script that relays gateway messages to all the clients and messages from a client are relayed to the gateway.
I thought someone else could be in the same situation so here you go..