@@ -0,0 +1,117 @@ | |||
import threading, sys, queue | |||
from .puppeteer import Controller, HardwareTest, TemperatureTest,\ | |||
ProtocolTest, ExportData, QueueStatus, CancelProtocol | |||
from .pupuicon import InitNetwork, NetworkOperator | |||
# Hack | |||
# FIXME: Does it mean `translator have should it's own package?. | |||
sys.modules['translator'] = sys.modules['limoControl.pupuicon.translator'] | |||
del sys.modules['limoControl.pupuicon.translator'] | |||
# Create `cancel', `gui', and `protocol_status` switches. Default to FALSE. | |||
cancel_switch = threading.Event() | |||
gui_status = threading.Event() | |||
protocol_status = threading.Event() | |||
def main(): | |||
""" This will forever try to re-start server in case of error.""" | |||
while True: | |||
try: | |||
print("GUI status is: " + str(gui_status.is_set())) | |||
# Set server-side | |||
Box_Socket = InitNetwork(PORT=10011, MAX_CONNECTIONS=1) | |||
# Wait here until connection happens. | |||
gui_status.set() # GUI status -> TRUE, user connected. | |||
print("GUI status is now: " + str(gui_status.is_set())) | |||
while True: | |||
if protocol_status.is_set(): | |||
print("Protocol finished, but data not retrieved.") | |||
if cancel_switch.is_set(): | |||
cancel_switch.clear() | |||
GUI = NetworkOperator(Box_Socket.Connection, | |||
BUFFER_SIZE=64) # Buffer in bytes. | |||
# Run `box' as a thread. `Box_Socket' can then be populated in | |||
# parallel (i.e. to cancel protocol). | |||
try: | |||
if GUI.command.__module__ == 'limoControl.pupuicon.translator._core': | |||
USR_INSTRUCTIONS = GUI.command | |||
if len(USR_INSTRUCTIONS.QueueTimes) > 1: | |||
# This is a normal protocol... | |||
BoxQueue = queue.Queue() | |||
Box = threading.Thread(target=Controller, | |||
args=(USR_INSTRUCTIONS, | |||
Box_Socket.Connection, | |||
cancel_switch, | |||
gui_status, BoxQueue, | |||
protocol_status)) | |||
Box.start() | |||
[LiMO, Protocol, QueueFile] = BoxQueue.get() | |||
elif len(USR_INSTRUCTIONS.QueueTimes) == 1: | |||
# This is a grab... | |||
print("User says: (Flexi)grab data.") | |||
BoxQueue = queue.Queue() | |||
Box = threading.Thread(target=Controller, | |||
args=(USR_INSTRUCTIONS, | |||
Box_Socket.Connection, | |||
cancel_switch, | |||
gui_status, BoxQueue, | |||
protocol_status)) | |||
Box.start() | |||
[_, Protocol, _] = BoxQueue.get() | |||
Box.join() # Wait until thread finishes. | |||
ExportData(Protocol, False, None, | |||
Box_Socket.Connection, | |||
gui_status, Test=True) | |||
protocol_status.clear() | |||
except AttributeError: | |||
# __module__ attribute does not exist, therefore | |||
# GUI.command does not contain protocol/grab information. | |||
print("User says: " + GUI.command + ".") | |||
if GUI.command == "Close Connection": | |||
Box_Socket.Socket.close() | |||
break # Necessary to break inner while-loop. | |||
elif GUI.command == "Test Hardware": | |||
print("Testing hardware...") | |||
HardwareTest(Box_Socket.Connection, gui_status) | |||
elif GUI.command == "Test Temperature": | |||
print("Testing heater...") | |||
TemperatureTest(Box_Socket.Connection, gui_status) | |||
elif GUI.command == "Test Protocol": | |||
print("Running test protocol...") | |||
Protocol = ProtocolTest(Box_Socket.Connection, | |||
cancel_switch, gui_status) | |||
ExportData(Protocol, False, False, | |||
Box_Socket.Connection, gui_status, Test=True) | |||
elif GUI.command == "Abort Protocol": | |||
# Turn hardware OFF before cancelling!! otherwise things | |||
# like HEATER can be left ON. | |||
print("Cancel Protocol.") | |||
if 'LiMO' in locals(): | |||
Box._stop() # Force-stop thread. | |||
Box.join() | |||
CancelProtocol(with_device=LiMO) | |||
else: | |||
# Restart light modulator without anything running. | |||
CancelProtocol() | |||
elif GUI.command == "Check Queue": | |||
try: | |||
if Protocol: | |||
print("Checking Queue...") | |||
QueueStatus(QueueFile, Box_Socket.Connection) | |||
except NameError: | |||
print("No protocol running.") | |||
elif GUI.command == "Retrieve data": | |||
ExportData(Protocol, False, QueueFile, | |||
Box_Socket.Connection, gui_status) | |||
protocol_status.clear() | |||
else: | |||
# GUI _always_ expects something coming back. | |||
# By returning a message, the interface won't stall. | |||
Box_Socket.Connection.sendall(str("::IDLE::").encode()) | |||
except (ConnectionResetError, BrokenPipeError, OSError) as err: | |||
Box_Socket.Socket.close() | |||
print("GUI status was: " + str(gui_status.is_set())) | |||
gui_status.clear() # GUI status -> FALSE, disconnect user. | |||
print("GUI status is now: " + str(gui_status.is_set())) | |||
print(err) | |||
print("\nRestarting server.") |
@@ -0,0 +1,119 @@ | |||
#!/usr/bin/env python | |||
# Copyright (C) 2018 Carlos Reding <rc_reding@teknik.io> | |||
# | |||
# Permission is hereby granted, free of charge, to any person obtaining | |||
# a copy of this software and associated documentation files (the | |||
# "Software"), to deal in the Software without restriction, including | |||
# without limitation the rights to use, copy, modify, merge, publish, | |||
# distribute, sublicense, and/or sell copies of the Software, and to | |||
# permit persons to whom the Software is furnished to do so, subject to | |||
# the following conditions: | |||
# | |||
# The above copyright notice and this permission notice shall be | |||
# included in all copies or substantial portions of the Software. | |||
# | |||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |||
# NONINFRINGEMENT. IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY | |||
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |||
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |||
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |||
# | |||
# Except as contained in this notice, the name(s) of the above copyright | |||
# holders shall not be used in advertising or otherwise to promote the sale, | |||
# use or other dealings in this Software without prior written authorization. | |||
"""Library to control a light modulator (LiMO) instrument.""" | |||
import os | |||
import sys | |||
from setuptools import setup, find_packages | |||
if sys.version_info[0] == 2: | |||
raise ValueError('This package requires Python 3.4 or above') | |||
elif sys.version_info[0] == 3: | |||
if not sys.version_info >= (3, 4): | |||
raise ValueError('This package requires Python 3.4 or above') | |||
else: | |||
raise ValueError('Unrecognized major version of Python') | |||
HERE = os.path.abspath(os.path.dirname(__file__)) | |||
# Workaround <http://www.eby-sarna.com/pipermail/peak/2010-May/003357.html> | |||
try: | |||
import multiprocessing | |||
except ImportError: | |||
pass | |||
__project__ = 'limoControl' | |||
__version__ = '1.0rc1' | |||
__author__ = 'Carlos Reding' | |||
__author_email__ = 'rc_reding@teknik.io' | |||
__url__ = 'https://git.teknik.io/rc_reding/limo-dev' | |||
__platform__ = 'Linux' | |||
__description__ = '' | |||
__classifiers__ = [ | |||
"Development Status :: 5 - Production/Stable", | |||
"Environment :: Console", | |||
"Intended Audience :: Education", | |||
"Intended Audience :: Science/Research", | |||
"License :: OSI Approved :: GNU Lesser General Public License v2 (LGPLv2)", | |||
"Programming Language :: Python :: 3", | |||
'Topic :: Adaptive Technologies', | |||
] | |||
__keywords__ = [ | |||
# 'raspberrypi', | |||
# 'camera', | |||
] | |||
__requires__ = [ | |||
'netifaces', | |||
'numpy', | |||
'scipy', | |||
'pigpio', | |||
'w1thermsensor', | |||
'picamera', | |||
# 'opencv-python>=3.1', # FIXME: Issues in RPi as opencv is self-compiled. | |||
] | |||
__extra_requires__ = { | |||
} | |||
__entry_points__ = { | |||
'console_scripts': [ 'srv_controller=limoControl:main'], | |||
} | |||
def main(): | |||
import io | |||
with io.open(os.path.join(HERE, 'README.md'), 'r') as readme: | |||
setup( | |||
name = __project__, | |||
version = __version__, | |||
description = __doc__, | |||
long_description = readme.read(), | |||
long_description_content_type = 'text/Markdown', | |||
classifiers = __classifiers__, | |||
author = __author__, | |||
author_email = __author_email__, | |||
url = __url__, | |||
platforms = __platform__, | |||
license = [ | |||
c.rsplit('::', 1)[1].strip() | |||
for c in __classifiers__ | |||
if c.startswith('License ::') | |||
][0], | |||
keywords = __keywords__, | |||
packages = find_packages(), | |||
install_requires = __requires__, | |||
extras_require = __extra_requires__, | |||
entry_points = __entry_points__, | |||
) | |||
if __name__ == '__main__': | |||
main() |
@@ -1,120 +0,0 @@ | |||
#!/bin/python3 | |||
import threading, sys, time, queue | |||
from puppeteer import Controller, HardwareTest, TemperatureTest,\ | |||
ProtocolTest, ExportData, QueueStatus, CancelProtocol | |||
from pupuicon import InitNetwork, NetworkOperator | |||
# Hack | |||
# FIXME: Does it mean `translator have should it's own package?. | |||
sys.modules['translator'] = sys.modules['pupuicon.translator'] | |||
del sys.modules['pupuicon.translator'] | |||
# Create `cancel', `gui', and `protocol_status` switches. Default to FALSE. | |||
cancel_switch = threading.Event() | |||
gui_status = threading.Event() | |||
protocol_status = threading.Event() | |||
# This will forever try to re-start server in case of error. | |||
while True: | |||
try: | |||
print("GUI status is: " + str(gui_status.is_set())) | |||
# Set server-side | |||
Box_Socket = InitNetwork(PORT=10011, MAX_CONNECTIONS=1) | |||
# Wait here until connection happens. | |||
gui_status.set() # GUI status -> TRUE, user connected. | |||
print("GUI status is now: " + str(gui_status.is_set())) | |||
while True: | |||
if protocol_status.is_set(): | |||
print("Protocol finished, but data not retrieved.") | |||
if cancel_switch.is_set(): | |||
cancel_switch.clear() | |||
GUI = NetworkOperator(Box_Socket.Connection, BUFFER_SIZE=64) # Buffer in bytes. | |||
# Create a new thread (box hardware independent of everything else). | |||
# Box_Socket can still be populated in parallel (i.e. to cancel protocol). | |||
try: | |||
if GUI.command.__module__ == 'pupuicon.translator._core': | |||
USR_INSTRUCTIONS = GUI.command | |||
if len(USR_INSTRUCTIONS.QueueTimes) > 1: | |||
# This is a normal protocol... | |||
BoxQueue = queue.Queue() | |||
Box = threading.Thread(target=Controller, args=(USR_INSTRUCTIONS, | |||
Box_Socket.Connection, | |||
cancel_switch, | |||
gui_status, | |||
BoxQueue, | |||
protocol_status)) | |||
Box.start() | |||
[LiMO, Protocol, QueueFile] = BoxQueue.get() | |||
elif len(USR_INSTRUCTIONS.QueueTimes) == 1: | |||
# This is a grab... | |||
print("User says: (Flexi)grab data.") | |||
BoxQueue = queue.Queue() | |||
Box = threading.Thread(target=Controller, args=(USR_INSTRUCTIONS, | |||
Box_Socket.Connection, | |||
cancel_switch, | |||
gui_status, | |||
BoxQueue, | |||
protocol_status)) | |||
Box.start() | |||
[_, Protocol, _] = BoxQueue.get() | |||
Box.join() # Wait until thread finishes (1 step only). | |||
ExportData(Protocol, False, None, Box_Socket.Connection, | |||
gui_status, Test=True) | |||
protocol_status.clear() | |||
except AttributeError: | |||
# __module__ attribute does not exist, therefore | |||
# GUI.command does not contain protocol/grab information. | |||
print("User says: " + GUI.command + ".") | |||
if GUI.command == "Close Connection": | |||
Box_Socket.Socket.close() | |||
break | |||
elif GUI.command == "Test Hardware": | |||
print("Testing hardware...") | |||
HardwareTest(Box_Socket.Connection, gui_status) | |||
elif GUI.command == "Test Temperature": | |||
print("Testing heater...") | |||
TemperatureTest(Box_Socket.Connection, gui_status) | |||
elif GUI.command == "Test Protocol": | |||
print("Running test protocol...") | |||
Protocol = ProtocolTest(Box_Socket.Connection, | |||
cancel_switch, gui_status) | |||
ExportData(Protocol, False, False, | |||
Box_Socket.Connection, gui_status, Test=True) | |||
elif GUI.command == "Abort Protocol": | |||
# Turn hardware OFF before cancelling!! otherwise things | |||
# like HEATER can be left ON. | |||
print("Cancel Protocol.") | |||
if 'LiMO' in locals(): | |||
Box._stop() | |||
Box.join() | |||
CancelProtocol(with_device=LiMO) | |||
else: | |||
# This steps allows to restart LiMO without anything running. | |||
CancelProtocol() | |||
elif GUI.command == "Check Queue": | |||
try: | |||
if Protocol: | |||
print("Checking Queue...") | |||
QueueStatus(QueueFile, Box_Socket.Connection) # Assumes `Protocol' exists. Greyed-out in GUI. | |||
except NameError: | |||
print("No protocol running.") | |||
pass | |||
elif GUI.command == "Retrieve data": # Assumes `Protocol' exists. Greyed-out in GUI. | |||
ExportData(Protocol, False, QueueFile, | |||
Box_Socket.Connection, gui_status) | |||
protocol_status.clear() | |||
else: | |||
# GUI _always_ expects something coming back. | |||
# By returning a message, the interface won't stall. | |||
Box_Socket.Connection.sendall(str("::IDLE::").encode()) | |||
except (ConnectionResetError, BrokenPipeError, OSError) as err: | |||
Box_Socket.Socket.close() | |||
print("GUI status was: " + str(gui_status.is_set())) | |||
gui_status.clear() # GUI status -> FALSE, disconnect user. | |||
print("GUI status is now: " + str(gui_status.is_set())) | |||
print(err) | |||
print("\nRestarting server.") | |||