def init(config={}): global cfg, printer, fd, num_axes, num_buttons, dead if cfg is not None: return configdata = { 'tick_time': .05, 'js': '/dev/input/js0', 'printer': '8000', 'dead': .1 } configdata.update(config) cfg = fhs.init(configdata) dead = float(cfg['dead']) printer = websocketd.RPC(cfg['printer'], tls=False) fd = os.open(cfg['js'], os.O_RDWR) version = ioctl(js.gversion, ctypes.c_uint32) if version != js.version: sys.stderr.write('version mismatch (%x != %x)' % (version, js.version)) num_axes = ioctl(js.gaxes, ctypes.c_uint8) num_buttons = ioctl(js.gbuttons, ctypes.c_uint8) axis_state[:] = [0.] * num_axes button_state[:] = [None] * num_buttons
def _tls_init(self): # Set up members for using tls, if requested. if self.tls in (False, '-'): self.tls = False return if self.tls in (None, True, ''): self.tls = fhs.init(packagename = 'network', config = {'tls': ''}, argv = os.getenv('NETWORK_OPTS', '').split())['tls'] if self.tls == '': self.tls = socket.getfqdn() elif self.tls == '-': self.tls = False return # Use tls. fc = fhs.read_data(os.path.join('certs', self.tls + os.extsep + 'pem'), opened = False, packagename = 'network') fk = fhs.read_data(os.path.join('private', self.tls + os.extsep + 'key'), opened = False, packagename = 'network') if fc is None or fk is None: # Create new self-signed certificate. certfile = fhs.write_data(os.path.join('certs', self.tls + os.extsep + 'pem'), opened = False, packagename = 'network') csrfile = fhs.write_data(os.path.join('csr', self.tls + os.extsep + 'csr'), opened = False, packagename = 'network') for p in (certfile, csrfile): path = os.path.dirname(p) if not os.path.exists(path): os.makedirs(path) keyfile = fhs.write_data(os.path.join('private', self.tls + os.extsep + 'key'), opened = False, packagename = 'network') path = os.path.dirname(keyfile) if not os.path.exists(path): os.makedirs(path, 0o700) os.system('openssl req -x509 -nodes -days 3650 -newkey rsa:4096 -subj "/CN=%s" -keyout "%s" -out "%s"' % (self.tls, keyfile, certfile)) os.system('openssl req -subj "/CN=%s" -new -key "%s" -out "%s"' % (self.tls, keyfile, csrfile)) fc = fhs.read_data(os.path.join('certs', self.tls + os.extsep + 'pem'), opened = False, packagename = 'network') fk = fhs.read_data(os.path.join('private', self.tls + os.extsep + 'key'), opened = False, packagename = 'network') self.tls_cert = fc self.tls_key = fk
def init(config = {}): global cfg, printer, fd, num_axes, num_buttons, dead if cfg is not None: return configdata = {'tick_time': .05, 'js': '/dev/input/js0', 'printer': '8000', 'dead': .1} configdata.update(config) cfg = fhs.init(configdata) dead = float(cfg['dead']) printer = websocketd.RPC(cfg['printer'], tls = False) fd = os.open(cfg['js'], os.O_RDWR) version = ioctl(js.gversion, ctypes.c_uint32) if version != js.version: sys.stderr.write('version mismatch (%x != %x)' % (version, js.version)) num_axes = ioctl(js.gaxes, ctypes.c_uint8) num_buttons = ioctl(js.gbuttons, ctypes.c_uint8) axis_state[:] = [0.] * num_axes button_state[:] = [None] * num_buttons
#!/usr/bin/python3 from PIL import Image import fhs import binascii config = fhs.init({'src': None, 'dpmm': 10, 'speed': 5, 'margin': 10}) im = Image.open(config['src']).convert(mode='1', dither=Image.FLOYDSTEINBERG) data = im.getdata() h, w = im.size print(';size: %d,%d' % (w, h)) print('G1 F%f' % (config['speed'] * 60)) for y in range(h): line = b'' # The full range is w/16, rounded up. That is (w+15)//16. Add one bit to make sure the laser is turned off at the end of the line. That makes it (w+16)//16 == w//16+1. for x in range(w // 16 + 1): for x2 in (0, 8): d = 0 for bit in range(8): b = data[y * w + x + x2 + bit] and 1 if x + x2 + bit < w else 0 d |= b << bit line += bytes((d, )) code = binascii.b2a_base64(line).strip().decode('utf-8', 'replace') print('G1 X%f Y%f' % (-config['margin'], y / config['dpmm'])) print('G1 X0') print('G1 X%f ;PATTERN:%s' % (w / config['dpmm'], code)) print('G1 X%f' % (w / config['dpmm'] + config['margin'])) print('G1 X0 Y0')
import json import traceback import fcntl import protocol config = fhs.init( packagename='franklin', config={ 'port': '8000', 'address': '', 'printer': '', 'blacklist': '/dev/(input/.*|ptmx|console|tty(printk|(S|GS)?\\d*))$', 'add-blacklist': '$', 'autodetect': 'True', 'predetect': 'stty -F #PORT# raw 115200 -echo -echoe -echok -echoke -echonl -echoprt', 'atexit': '', 'allow-system': '^$', 'admin': '', 'expert': '', 'user': '', 'done': '', 'local': '', 'log': '', 'tls': 'True', }) # }}} # Global variables. {{{ httpd = None default_printer = (None, None)
it switches a lot) which turns the motor on when active. The sewing machine should be set up with very low pressure on the foot, so the fabric can move underneath it without lifting the foot. If possible, there should be no transport from below. The stitch width and length should be set to 0. Make sure that the embroidery loop moves properly over the surface of the sewing machine. """ import websocketd import time import fhs config = fhs.init({'port': 8000, 'tls': 'False', 'motor': 3, 'sensor': 4}) motor = int(config['motor']) sensor = int(config['sensor']) tls = config['tls'].lower() != 'false' p = websocketd.RPC(config['port'], tls=tls) ''' Procedure: -> wait for confirm motor on needle down -> wait for gpio off needle up -> wait for gpio on motor off -> confirm Franklin moves repeat
import protocol config = fhs.init( packagename='franklin', config={ 'port': '8000', # Port to listen on. 'address': '', # Address to listen on. Mainly intended for RPi, which cannot handle IPv6 and needs 0.0.0.0 here to force IPv4. 'blacklist': '/dev/(input/.*|ptmx|console|tty(printk|(GS)?\\d*))$', # Which serial ports to refuse detecting on. 'add-blacklist': '$', # Which serial ports to additionally refuse detecting on. Used to add ports to the list without losing the defaults. 'autodetect': True, # Whether new machines are autodetected on new ports, and after flashing. 'predetect': 'stty -F $PORT raw 115200 -echo -echoe -echok -echoke -echonl -echoprt', # What to do to a port before detecting a machine. 'controller': '/usr/lib/franklin/controller.py --dev "$PORT"', # How to start a controller subprocess 'allow-system': '^$', # Which commands are allowed through system comments in G-Code. 'admin': '', # Admin password; defaults to expert password. 'expert': '', # Expert password; defaults to user password. 'user': '', # User password; defaults to no password. 'done': '', # Program to run when a job is done. 'log': '', # Enable logging to a given logfile. 'tls': 'False', # Whether TLS is used on the network connection. If using Apache's virtual proxy method, this must be False, because Apache handles the encryption. 'arc': False, # Whether arc detection in G-Code is enabled. This is False by default, because it is broken. }) # }}}
#!/usr/bin/python3 from PIL import Image import fhs import binascii config = fhs.init({'src': None, 'dpmm': 10, 'speed': 5, 'margin': 10}) im = Image.open(config['src']).convert(mode = '1', dither = Image.FLOYDSTEINBERG) data = im.getdata() h, w = im.size print(';size: %d,%d' % (w, h)) print('G1 F%f' % (config['speed'] * 60)) for y in range(h): line = b'' # The full range is w/16, rounded up. That is (w+15)//16. Add one bit to make sure the laser is turned off at the end of the line. That makes it (w+16)//16 == w//16+1. for x in range(w // 16 + 1): for x2 in (0, 8): d = 0 for bit in range(8): b = data[y * w + x + x2 + bit] and 1 if x + x2 + bit < w else 0 d |= b << bit line += bytes((d,)) code = binascii.b2a_base64(line).strip().decode('utf-8', 'replace') print('G1 X%f Y%f' % (-config['margin'], y / config['dpmm'])) print('G1 X0') print('G1 X%f ;PATTERN:%s' % (w / config['dpmm'], code)) print('G1 X%f' % (w / config['dpmm'] + config['margin'])) print('G1 X0 Y0')
fhs.option('controller', 'Run this command to handle a controller on a serial port', default='/usr/lib/franklin/controller.py --dev "$PORT"') fhs.option('allow-system', 'Only allow system commands that match this regular expression', default='^$') fhs.option('admin', 'Admin password', default='') fhs.option('expert', 'Expert user password', default='') fhs.option('user', 'Local user password', default='') fhs.option('remote', 'Remote user password', default='') fhs.option('done', 'Run this command when a job is done', default='') fhs.option('log', 'Enable logging to a given logfile') fhs.option('tls', 'Enable TLS. It is recommended to let Apache handle this', argtype=bool) config = fhs.init(packagename='franklin') # }}} # Global variables. {{{ httpd = None ports = {} autodetect = not config['noautodetect'] tls = config['tls'] machines = {} log('whitelist: %s' % config['whitelist']) # }}} class Server(websocketd.RPChttpd): # {{{ def auth_message(self, connection, is_websocket): path = connection.address.path
data[spot] = item objects.remove(item) accessible.add(item) for item_addr, check_addr in drop_addrs: item = data[item_addr + itemoffset] data[check_addr + codeoffset] = 0x20 + item - 1 if item < 8 else 0xa0 + item - 8 - 1 return data try: import fhs import websocketd config = fhs.init({'port': 9999}) server = websocketd.Httpd(config['port'], None, httpdirs=['html'], tls=False) def new_page(connection, path=None): if connection.address.path != '/random.rom': return default_page(connection, path) args = {} for arg in ('initial', 'silencer', 'card7', 'card8', 'drops', 'bag'): args[arg] = arg not in connection.query or connection.query[arg][ 0].lower() not in ('0', 'false') if 'rom' in connection.query: args['rom'] = connection.query['rom'][0]
import serial import json import traceback import fcntl import protocol config = fhs.init(packagename = 'franklin', config = { 'port': '8000', # Port to listen on. 'address': '', # Address to listen on. Mainly intended for RPi, which cannot handle IPv6 and needs 0.0.0.0 here to force IPv4. 'whitelist': r'', # Which serial ports to attempt detecting on. Ports that are both whitelisted and blacklisted are not included. 'blacklist': r'/dev/(input/.*|ptmx|console|tty(printk|(GS)?\d*))$', # Which serial ports to refuse detecting on. 'add-blacklist': r'$', # Which serial ports to additionally refuse detecting on. Used to add ports to the list without losing the defaults. 'autodetect': True, # Whether new machines are autodetected on new ports, and after flashing. 'predetect': 'stty -F $PORT raw 115200 -echo -echoe -echok -echoke -echonl -echoprt', # What to do to a port before detecting a machine. 'controller': '/usr/lib/franklin/controller.py --dev "$PORT"', # How to start a controller subprocess 'allow-system': '^$', # Which commands are allowed through system comments in G-Code. 'admin': '', # Admin password. 'expert': '', # Expert password. 'user': '', # User password. 'remote': '', # Remote password. 'done': '', # Program to run when a job is done. 'log': '', # Enable logging to a given logfile. 'tls': 'False', # Whether TLS is used on the network connection. If using Apache's virtual proxy method, this must be False, because Apache handles the encryption. 'arc': False, # Whether arc detection in G-Code is enabled. This is False by default, because it is broken. }) # }}} # Global variables. {{{ httpd = None ports = {} autodetect = config['autodetect']
add_item(data, 0 if extreme else item, spots, item_offset, code_offset, items[spot]) found.add(item) for i in all_items: add_item(data, 0 if extreme else i, spots, item_offset, code_offset) found.add(i) while len(spots) > 0: add_item(data, 0 if extreme else default_item(), spots, item_offset, code_offset) return bytes(data) # }}} try: import fhs import websocketd fhs.option('port', 'port to listen on', default = '9999') config = fhs.init() server = websocketd.Httpd(config['port'], None, httpdirs = ['html'], tls = False) def new_page(connection, path = None): if connection.address.path != '/random.rom': return default_page(connection, path) close_doors = None if 'doors' not in connection.query or connection.query['doors'][-1] == 'keep' else True if connection.query['doors'][-1] == 'close' else False show_doors = 'showdoor' in connection.query and connection.query['showdoor'][-1].lower() == 'true' extreme = 'extreme' in connection.query and connection.query['extreme'][-1].lower() == 'true' print(connection.query, close_doors, show_doors, extreme) data = randomize(connection.query['rom'][0] if 'rom' in connection.query else None, close_doors, show_doors, extreme) return server.reply(connection, 200, bytes(data), 'application/octet-stream') default_page = server.page server.page = new_page
import time import serial import json import traceback import fcntl import protocol config = fhs.init(packagename = 'franklin', config = { 'port': '8000', 'address': '', 'printer': '', 'blacklist': '/dev/(input/.*|ptmx|console|tty(printk|(S|GS)?\\d*))$', 'add-blacklist': '$', 'autodetect': 'True', 'predetect': 'stty -F #PORT# raw 115200 -echo -echoe -echok -echoke -echonl -echoprt', 'atexit': '', 'allow-system': '^$', 'admin': '', 'expert': '', 'user': '', 'done': '', 'local': '', 'log': '', 'tls': 'True', }) # }}} # Global variables. {{{ httpd = None default_printer = (None, None) ports = {} autodetect = config['autodetect'].lower() == 'true'
def Game(): # Main function to start a game. {{{ global server, title_game, have_2d, have_3d, _num_players # Set up the game name. if not hasattr(__main__, 'name') or __main__.name is None: __main__.name = os.path.basename(sys.argv[0]).capitalize() # Initialize fhs module. if not fhs.initialized: fhs.init({}, packagename = __main__.name.lower(), game = True) # Set up other constants. if not hasattr(__main__, 'autokill'): __main__.autokill = True have_2d = fhs.read_data(os.path.join('html', '2d'), dir = True, opened = False) is not None have_3d = fhs.read_data(os.path.join('html', '3d'), dir = True, opened = False) is not None or not have_2d # Fill in min and max if not specified. assert hasattr(__main__, 'num_players') if isinstance(__main__.num_players, int): _num_players = (__main__.num_players, __main__.num_players) else: _num_players = __main__.num_players assert 1 <= _num_players[0] and (_num_players[1] is None or _num_players[0] <= _num_players[1]) # Build asset string for inserting in js. for subdir, use_3d in (('2d', False), ('3d', True)): targets = [] for base in ('img', 'jta', 'gani', 'audio', 'text'): for d in (os.path.join('html', base), os.path.join('html', subdir, base)): for p in fhs.read_data(d, dir = True, multiple = True, opened = False): targets.extend(f.encode('utf-8') for f in os.listdir(p) if not f.startswith('.') and not os.path.isdir(os.path.join(p, f))) if len(targets) > 0: loader_js[use_3d] = b'\n'.join(b"\tplease.load('" + f + b"');" for f in targets) else: # Nothing to load, but force the "finished loading" event to fire anyway. loader_js[use_3d] = b'\twindow.dispatchEvent(new CustomEvent("mgrl_media_ready"));' # Set up commands. cmds['leave'] = {None: leave} if hasattr(__main__, 'commands'): for c in __main__.commands: cmds[c] = {None: __main__.commands[c]} # Start up websockets server. config = fhs.module_get_config('webgame') httpdirs = [fhs.read_data(x, opened = False, multiple = True, dir = True) for x in ('html', os.path.join('html', '2d'), os.path.join('html', '3d'))] server = websocketd.RPChttpd(config['port'], Connection, tls = config['tls'], httpdirs = httpdirs[0] + httpdirs[1] + httpdirs[2]) server.handle_ext('png', 'image/png') server.handle_ext('jpg', 'image/jpeg') server.handle_ext('jpeg', 'image/jpeg') server.handle_ext('gif', 'image/gif') server.handle_ext('gani', 'text/plain') server.handle_ext('wav', 'audio/wav') server.handle_ext('ogg', 'audio/ogg') server.handle_ext('mp3', 'audio/mp3') server.handle_ext('jta', 'application/octet-stream') server.handle_ext('txt', 'text/plain') server.handle_ext('frag', 'text/plain') server.handle_ext('vert', 'text/plain') server.handle_ext('glsl', 'text/plain') # Set up title page. if hasattr(__main__, 'Title'): title_game = Instance(__main__.Title, '') else: title_game = Instance(Title, '') log('Game "%s" started' % __main__.name) # Main loop. websocketd.fgloop()
import traceback import fcntl import protocol config = fhs.init(packagename = 'franklin', config = { 'port': '8000', 'address': '', 'printer': '', 'audiodir': '', 'blacklist': '/dev/(input/.*|ptmx|console|tty(printk|(S|GS)?\\d*))$', 'add-blacklist': '$', 'autodetect': 'True', 'predetect': 'stty -F #PORT# raw 115200', 'atexit': '', 'avrdude': '/usr/bin/avrdude', 'allow-system': '^$', 'admin': '', 'expert': '', 'user': '', 'done': '', 'local': '', 'driver': '', 'cdriver': '', 'log': '', 'tls': 'True', 'avrdudeconfig': '/usr/lib/franklin/avrdude.conf' }) if config['audiodir'] == '': config['audiodir'] = fhs.write_cache(name = 'audio', dir = True), if config['driver'] == '': config['driver'] = fhs.read_data('driver.py', opened = False)
it switches a lot) which turns the motor on when active. The sewing machine should be set up with very low pressure on the foot, so the fabric can move underneath it without lifting the foot. If possible, there should be no transport from below. The stitch width and length should be set to 0. Make sure that the embroidery loop moves properly over the surface of the sewing machine. """ import websocketd import time import fhs config = fhs.init({'port': 8000, 'tls': 'False', 'motor': 3, 'sensor': 4}) motor = int(config['motor']) sensor = int(config['sensor']) tls = config['tls'].lower() != 'false' p = websocketd.RPC(config['port'], tls = tls) ''' Procedure: -> wait for confirm motor on needle down -> wait for gpio off needle up -> wait for gpio on motor off -> confirm Franklin moves
# GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. # }}} # Imports import sys import os import Image import pickle import readini import fhs # Config. config = fhs.init({'dinkdir': '/usr/share/games/dink/dink', 'dmoddir': os.path.join(fhs.HOME, 'dmods'), 'editdir': None, 'freedink': '/usr/bin/freedink'}, packagename = 'pydink') dinkdir = os.path.realpath(config['dinkdir']) dmoddir = os.path.realpath(config['dmoddir']) editdir = os.path.realpath(config['editdir']) freedink = os.path.realpath(config['freedink']) fhs.save_config(config) readini.setup(dinkdir) savedir = fhs.write_cache(dir = True) # Create data to be cached. err = '' try: harddata, harddefaults, tilefiles = readini.read_hard() tilefiles = [t[0] for t in tilefiles] collections, sequences, codes = readini.read_ini()