From d186a5fe3c5ffe5f2a8f0f0f1baec9bc5ad9b981 Mon Sep 17 00:00:00 2001 From: Benjamin Braatz Date: Tue, 12 Jan 2021 06:58:33 +0100 Subject: [PATCH] Initial commit --- .gitignore | 1 + LICENSE | 19 ++++++++ README.md | 2 + conf.json | 53 +++++++++++++++++++++ graphit_controlpi/__init__.py | 0 graphit_controlpi/main.py | 86 +++++++++++++++++++++++++++++++++++ setup.py | 28 ++++++++++++ 7 files changed, 189 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md create mode 100644 conf.json create mode 100644 graphit_controlpi/__init__.py create mode 100644 graphit_controlpi/main.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c18dd8d --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..86da0a6 --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 Graph-IT GmbH + +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 +AUTHORS OR COPYRIGHT HOLDERS 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f2de5d --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Main Module for Machine Control Pi + diff --git a/conf.json b/conf.json new file mode 100644 index 0000000..f60ebe7 --- /dev/null +++ b/conf.json @@ -0,0 +1,53 @@ +{ "i/o cards": + [ { "name": "A1", + "type": "output", + "address": 56, + "pins": + [ [ "A1-1", "T1-1" ], [ "A1-2", "T1-2" ], + [ "A1-3", "T1-3" ], [ "A1-4", "T1-4" ], + [ "A1-5", "T1-5" ], [ "A1-6", "T1-6" ], + [ "A1-7", "T1-7" ], [ "A1-8", "T1-8" ] ] }, + { "name": "A2", + "type": "output", + "address": 57, + "pins": + [ [ "A2-1", "T1-9" ], [ "A2-2", "T1-10" ], + [ "A2-3", "T1-11" ], [ "A2-4", "T1-12" ], + [ "A2-5", "T1-13" ], [ "A2-6", "T1-14" ], + [ "A2-7", "T1-15" ], [ "A2-8", "T1-16" ] ] }, + { "name": "E1", + "type": "input", + "address": 32, + "interrupt pin": 4, + "pins": + [ [ "E1-1", "T1-18" ], [ "E1-2", "T1-19" ], + [ "E1-3", "T1-20" ], [ "E1-4", "T1-21" ], + [ "E1-5", "T1-22" ], [ "E1-6", "T1-23" ], + [ "E1-7", "T1-24" ], [ "E1-8", "T1-25" ] ] }, + { "name": "E2", + "type": "input", + "address": 33, + "interrupt pin": 17, + "pins": + [ [ "E2-1", "T1-26" ], [ "E2-2", "T1-27" ], + [ "E2-3", "T1-28" ], [ "E2-4", "T1-29" ], + [ "E2-5", "T1-30" ], [ "E2-6", "T1-31" ], + [ "E2-7", "T1-32" ], [ "E2-8", "T1-33" ] ] }, + { "name": "E3", + "type": "input", + "address": 34, + "interrupt pin": 27, + "pins": + [ [ "E3-1", "T2-1" ], [ "E3-2", "T2-2" ], + [ "E3-3", "T2-3" ], [ "E3-4", "T2-4" ], + [ "E3-5", "T2-5" ], [ "E3-6", "T2-6" ], + [ "E3-7", "T2-7" ], [ "E3-8", "T2-8" ] ] }, + { "name": "E4", + "type": "input", + "address": 35, + "interrupt pin": 22, + "pins": + [ [ "E4-1", "T2-9" ], [ "E4-2", "T2-10" ], + [ "E4-3", "T2-11" ], [ "E4-4", "T2-12" ], + [ "E4-5", "T2-13" ], [ "E4-6", "T2-14" ], + [ "E4-7", "T2-15" ], [ "E4-8", "T2-16" ] ] } ] } diff --git a/graphit_controlpi/__init__.py b/graphit_controlpi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/graphit_controlpi/main.py b/graphit_controlpi/main.py new file mode 100644 index 0000000..923ea75 --- /dev/null +++ b/graphit_controlpi/main.py @@ -0,0 +1,86 @@ +import sys +import json +import websockets +from graphit_pin import PCF8574Output, PCF8574Input, GPIOInputPin + +pins = {} +out_queue = asyncio.Queue() + + +def process_configuration(conf): + + def callback_factory(pin_name): + settable = pins[pin_name].settable + + def callback(value): + out_queue.put({'event': 'pinstate', 'pin': pin_name, + 'settable': settable, 'value': value, + 'changed': True}) + return callback + + if 'i/o cards' in conf: + for card_conf in conf['i/o cards']: + card = None + if card_conf['type'] == 'output': + card = PCF8574Output(card_conf['address']) + elif card_conf['type'] == 'input': + card = PCF8574Input(card_conf['address'], + GPIOInputPin(card_conf['interrupt pin'], + up=True)) + if card is not None: + for i in range(8): + pin = card.getPin(i) + pin_names = card_conf['pins'][i] + for pin_name in pin_names: + pins[pin_name] = pin + pin.on('change', callback_factory(pin_name)) + + +async def process_command(command): + if command['command'] == 'setpin': + if command['pin'] in pins: + pins[command['pin']].value = command['value'] + elif command['command'] == 'getpin': + if command['pin'] in pins: + pin = pins[command['pin']] + out_queue.put({'event': 'pinstate', 'pin': command['pin'], + 'settable': pin.settable, 'value': pin.value, + 'changed': False}) + elif command['command'] == 'getallpins': + for pin_name in pins: + pin = pins[pin_name] + out_queue.put({'event': 'pinstate', 'pin': pin_name, + 'settable': pin.settable, 'value': pin.value, + 'changed': False}) + + +async def command_handler(websocket, path): + async for message in websocket: + command = json.loads(message) + await process_command(command) + + +async def event_handler(websocket, path): + while True: + event = await out_queue.get() + message = json.dumps(event) + await websocket.send(message) + + +async def handler(websocket, path): + command_task = asyncio.ensure_future(command_handler(websocket, path)) + event_task = asyncio.ensure_future(event_handler(websocket, path)) + done, pending = await asyncio.wait( + [command_task, event_task], + return_when=asyncio.FIRST_COMPLETED, + ) + for task in pending: + task.cancel() + +if __name__ == '__main__': + with open(sys.argv[1]) as json_data: + conf = json.load(json_data) + process_configuration(conf) + start_server = websockets.serve(handler, 'localhost', 5678) + asyncio.get_event_loop().run_until_complete(start_server) + asyncio.get_event_loop().run_forever() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..cf9e697 --- /dev/null +++ b/setup.py @@ -0,0 +1,28 @@ +import setuptools + +with open("README.md", "r") as readme_file: + long_description = readme_file.read() + +setuptools.setup( + name="graphit-controlpi", + version="0.2.0", + author="Graph-IT GmbH", + author_email="info@graph-it.com", + description="Main Module for Machine Control Pi", + long_description=long_description, + long_description_content_type="text/markdown", + url="http://docs.graph-it.com/graphit/controlpi-py", + packages=setuptools.find_packages(), + setup_requires=[ + "wheel" + ], + install_requires=[ + "websockets", + "graphit-pin @ git+git://git.graph-it.com/graphit/pin-py.git", + ], + classifiers=[ + "Programming Language :: Python", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], +) -- 2.34.1