--- /dev/null
+__pycache__/
--- /dev/null
+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.
--- /dev/null
+# Main Module for Machine Control Pi
+
--- /dev/null
+{ "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" ] ] } ] }
--- /dev/null
+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()
--- /dev/null
+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",
+ ],
+)