-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
38d2d01
commit ebff67b
Showing
3 changed files
with
228 additions
and
2 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
from simple_websocket_server import WebSocketServer, WebSocket | ||
import json | ||
import argparse | ||
|
||
|
||
class RobusEmulator(WebSocket): | ||
prev_node = None | ||
ptpa = False # Linked to prev | ||
ptpb = False # Linked to next | ||
ptpa_poke = False | ||
ptpb_poke = False | ||
next_node = None | ||
msg_index = 0 | ||
|
||
def handle(self): | ||
if isinstance(self.data, str): | ||
# This is a PTP command | ||
print("\nI receive : " + str(self.data) + | ||
" from " + str(self.address)) | ||
|
||
# PTP emulation: | ||
# Because PTP have been designed for real time response, the Robus algorythm is not really friendly to PTP management over WebSocket. | ||
# This broker have to drive data in a specific way allowing to make it work. | ||
# Robus HAL will send messages only during PTP reset state and read line. | ||
# Read_line mean Poke. When we have this we can set the line depending on the presence of another node and save this poke state on the line | ||
# The next reset received will need to be send to the other node. | ||
# | ||
# if (ptp line read (PTP up) : | ||
# if (a node is connected) : | ||
# send state 1 to the other node | ||
# send state 1 back | ||
# pass this ptp to poking | ||
# else : | ||
# send state 0 back | ||
# if (PTP down and ptp is poking) : | ||
# send state to the other node | ||
|
||
# PTPA | ||
if self.data[3] == 'A': | ||
# We get a PTPA data | ||
|
||
if (self.data[4] == '1'): | ||
if (self.prev_node != None): | ||
print("\t\tPTPB1 val sent to the node", | ||
str(self.prev_node.address)) | ||
self.prev_node.send_message("PTPB1") | ||
print("\t\tPTPA1 val sent back to the node", | ||
str(self.address)) | ||
self.send_message("PTPA1") | ||
self.prev_node.ptpb_poke = True | ||
self.ptpa_poke = True | ||
else: | ||
print("\t\tPTPA0 val sent back to the node", | ||
str(self.address)) | ||
self.send_message("PTPA0") | ||
|
||
if (self.data[4] == '0' and self.ptpa_poke == True and self.prev_node != None): | ||
print("\t\tPTPB0 val sent to the node", | ||
str(self.prev_node.address)) | ||
self.prev_node.send_message("PTPB0") | ||
self.prev_node.ptpb_poke = False | ||
self.ptpa_poke = False | ||
|
||
# PTPB | ||
if self.data[3] == 'B': | ||
# We get a PTPB data | ||
|
||
if (self.data[4] == '1'): | ||
if (self.next_node != None): | ||
print("\t\tPTPA1 val sent to the node", | ||
str(self.next_node.address)) | ||
self.next_node.send_message("PTPA1") | ||
print("\t\tPTPB1 val sent back to the node", | ||
str(self.address)) | ||
self.send_message("PTPB1") | ||
self.next_node.ptpa_poke = True | ||
self.ptpb_poke = True | ||
else: | ||
print("\t\tPTPB0 val sent back to the node", | ||
str(self.address)) | ||
self.send_message("PTPB0") | ||
|
||
if (self.data[4] == '0' and self.ptpb_poke == True and self.next_node != None): | ||
print("\t\tPTPA0 val sent to the node", | ||
str(self.next_node.address)) | ||
self.next_node.send_message("PTPA0") | ||
self.next_node.ptpa_poke = False | ||
self.ptpb_poke = False | ||
|
||
else: | ||
# This is a broadcast message | ||
print(str(self.msg_index)+" Data received from " + str(self.address)) | ||
self.msg_index += 1 | ||
for client in clients: | ||
if client != self: | ||
client.send_message(self.data) | ||
|
||
def connected(self): | ||
print(self.address, 'connected') | ||
clients.append(self) | ||
# Save links to other nodes | ||
if len(clients) >= 2: | ||
self.prev_node = clients[-2] | ||
self.prev_node.next_node = clients[-1] | ||
print("connect PTPB of " + str(self.prev_node.address) + | ||
" with PTPA of " + str(self.address)) | ||
|
||
def handle_close(self): | ||
print(self.address, 'closed') | ||
# Save links to other nodes | ||
if self.next_node != None: | ||
self.next_node.prev_node = self.prev_node | ||
if self.prev_node != None: | ||
self.prev_node.next_node = self.next_node | ||
clients.remove(self) | ||
|
||
|
||
## Parse arguments ## | ||
parser = argparse.ArgumentParser(description='Robus WebSocket emulator broker\n', | ||
formatter_class=argparse.RawTextHelpFormatter) | ||
# General arguments | ||
parser.add_argument("-p", "--port", metavar="PORT", action="store", | ||
help="The port used by the websocket.\n" | ||
"By default port = 8000.\n", | ||
default=8000) | ||
parser.add_argument("--ip", metavar="IP", action="store", | ||
help="The ip used by the websocket.\n" | ||
"By default ip = '127.0.0.1'.\n", | ||
default='127.0.0.1') | ||
|
||
args = parser.parse_args() | ||
clients = [] | ||
|
||
server = WebSocketServer(args.ip, args.port, RobusEmulator) | ||
print("WebSocket Robus emulation is deprecaated since Luos_engine 3.1.0, please consider using a WebSocket network instead.\n") | ||
print("WebSocket Robus emulation opened on " + | ||
str(args.ip) + ":" + str(args.port)) | ||
server.serve_forever() |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
from simple_websocket_server import WebSocketServer, WebSocket | ||
import json | ||
import argparse | ||
|
||
PING = 0 | ||
END = 1 | ||
OK = 2 | ||
NOK = 3 | ||
|
||
class WsBroker(WebSocket): | ||
pinged = False | ||
next_node = None | ||
global pinger | ||
|
||
def handle(self): | ||
if len(self.data) == 1: | ||
if len(pinger) == 0: | ||
# Data should be a ping | ||
if self.data[0] != PING: | ||
print("Error: received data is not a ping, received data is " + str(self.data[0])) | ||
else: | ||
pinger.append(self) | ||
find_someone = False | ||
# This is a ping command, find the next unpinged node and ping it | ||
for client in clients: | ||
if client != self and client.pinged == False: | ||
# We have someone to ping | ||
find_someone = True | ||
client.pinged = True | ||
client.send_message([PING]) | ||
# ack the ping to the sender | ||
self.send_message([OK]) | ||
break | ||
if find_someone == False: | ||
# We have no one to ping, this branch is finished, we can send a NOK to this ping and reset the pinged state of all nodes | ||
self.send_message([NOK]) | ||
pinger.remove(pinger[0]) | ||
for client in clients: | ||
client.pinged = False | ||
else: | ||
# Data should be an end | ||
if self.data[0] != END: | ||
print("Error: received data is not an end, received data is " + str(self.data[0]) + " from " + str(self.address)) | ||
else: | ||
# send the end to the pinger | ||
pinger[0].send_message([END]) | ||
#remove the pinger | ||
pinger.remove(pinger[0]) | ||
else: | ||
# This is a broadcast message | ||
#print(str(len(self.data)) + str(" Data received from " + str(self.address))) | ||
for client in clients: | ||
if client != self: | ||
client.send_message(self.data) | ||
|
||
def connected(self): | ||
print(self.address, 'connected\n') | ||
clients.append(self) | ||
|
||
def handle_close(self): | ||
print(self.address, 'closed') | ||
clients.remove(self) | ||
|
||
|
||
## Parse arguments ## | ||
parser = argparse.ArgumentParser(description='Luos_engine WebSocket network broker\n', | ||
formatter_class=argparse.RawTextHelpFormatter) | ||
# General arguments | ||
parser.add_argument("-p", "--port", metavar="PORT", action="store", | ||
help="The port used by the websocket.\n" | ||
"By default port = 8000.\n", | ||
default=8000) | ||
parser.add_argument("--ip", metavar="IP", action="store", | ||
help="The ip used by the websocket.\n" | ||
"By default ip = '127.0.0.1'.\n", | ||
default='127.0.0.1') | ||
|
||
args = parser.parse_args() | ||
clients = [] | ||
pinger = [] | ||
|
||
server = WebSocketServer(args.ip, args.port, WsBroker) | ||
print("Luos_engine WebSocket network broker opened on " + | ||
str(args.ip) + ":" + str(args.port)) | ||
server.serve_forever() |
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