def readerCallback(char, spacing): global msg, bracket if spacing * 3 * myReader.dotLen > 20000 and char != '~': # dropped packet msg += ' QN ? QJ ' for i in range(0, len(char)): if char[i] == '[': msg += ' QN ' bracket = True elif char[i] == ']': msg += ' QJ ' bracket = False elif bracket: if char[i] == '.': msg += 'E' elif char[i] == '-': msg += 'T' else: msg += '?' else: msg += char if msg[-1] == '+': log.log('Weather.py: {} @ {:.1f} wpm ({} ms)'.format( msg, 1200. / myReader.dotLen, myReader.truDot)) mySender.__init__(myReader.wpm) # send at same speed as received sendForecast(msg) myReader.setWPM(WPM) msg = ''
code = mySender.encode(char) if code: send(code) send((-1000, +1)) # close circuit after 1 sec time.sleep(artPause) time.sleep(grpPause - artPause) global artPause global days global grpPause global idText global uri global wait log.log('Starting Feed {0}'.format(VERSION)) try: arg_parser = argparse.ArgumentParser(description="Morse wire feed", parents=\ [\ config.serial_port_override, \ config.code_type_override, \ config.interface_type_override, \ config.sound_override, \ config.sounder_override, \ config.spacing_override, \ config.server_url_override, \ config.min_char_speed_override, \ # config.text_speed_override, \ # Specified as positional arg. #4 # config.wire_override, \ # Specified as positional arg. #1
try: import sys import time import threading from pykob import config, log, kob, internet VERSION = '1.5' PORT = config.serial_port # serial port for KOB interface SOUND = config.sound # whether to enable computer sound for sounder TIMEOUT = 30.0 # time to send after last indication of live listener (sec) TICK = (-1, +1, -200, +1, -200, +2) + 3 * (-200, +2) NOTICK = 5 * (-200, +2) MARK = (-1, +1) + 9 * (-200, +1) + (-200, +2) log.log('Starting Time {0}'.format(VERSION)) nargs = len(sys.argv) mode = sys.argv[1][0] if nargs > 1 else 'c' if nargs > 2: wire = int(sys.argv[2]) idText = sys.argv[3] else: wire = None myKOB = kob.KOB(PORT, SOUND) if wire: myInternet = internet.Internet(idText) myInternet.connect(wire) time.sleep(1)
def sendForecast(msg): m = re.search(r'WX(.{4,5})\+', msg) if not m: send('~ ? ' + msg[1:-1] + ' ? +') log.log('Weather.py: Invalid request') return station = m.group(1) # Station data url = 'https://api.weather.gov/stations/' + station req = Request(url) req.add_header('User-Agent', 'MorseKOB/[email protected]') req.add_header('Accept', 'application/geo+json') try: s = urlopen(req).read().decode('utf-8') except: send('~ WX ' + station + ' UNKNOWN +') log.err('Weather.py: Can\'t open ' + url) return if DEBUG: print('Station data:', s) m = re.search( r'"coordinates":\s*\[\s*(.+?),\s+(.+?)\s*\].*?"name":\s*"(.*?)[,"]', s, FLAGS) if not m: send('~ WX ' + station + ' UNAVAILABLE +') log.log('Weather.py: Can\'t find forecast for ' + station) return lon = m.group(1) lat = m.group(2) name = m.group(3) if DEBUG: print('lon, lat, name:', lon, lat, name) send('~ WX FOR ' + name + ' = ') # Current conditions url = 'https://api.weather.gov/stations/' + station + '/observations/current' req = Request(url) req.add_header('User-Agent', 'MorseKOB/[email protected]') req.add_header('Accept', 'application/geo+json') try: s = urlopen(req).read().decode('utf-8') except: send('CURRENT WX UNAVAILABLE +') log.err('Weather.py: Can\'t open ' + url) return if DEBUG: print('Current wx data:', s) m = re.search( r'"timestamp":\s*"(.*?)".*?"textDescription":\s*"(.*?)".*?"temperature":.*?"value":\s*(.*?),', s, FLAGS) if not m: send('CURRENT WX MISSING +') log.log('Weather.py: Can\'t parse forecast ' + station) return timestamp = m.group(1) cdx = m.group(2) temp = m.group(3) if DEBUG: print('time, cdx, temp:', timestamp, cdx, temp) try: t = int(float(temp) * 1.8 + 32.5) send('NOW {} AND {} DEG = '.format(cdx, t)) except: send('NOW {} = '.format(cdx)) log.log('Weather.py: Current temp error: ' + temp) # Forecast url = 'https://api.weather.gov/points/{},{}/forecast'.format(lat, lon) req = Request(url) req.add_header('User-Agent', 'MorseKOB/[email protected]') req.add_header('Accept', 'application/geo+json') try: s = urlopen(req).read().decode('utf-8') except: send('FORECAST UNAVAILABLE +') log.err('Weather.py: Can\'t open ' + url) return if DEBUG: print('Forecast data:', s) m = re.search( r'"name":\s*"(.*?)".*?"detailedForecast":\s*"(.*?)".*?"name":\s*"(.*?)".*?"detailedForecast":\s*"(.*?)"', s, FLAGS) if not m: send('FORECAST MISSING +') log.log('Weather.py: Can\'t parse forecast ' + station) return time1 = m.group(1) forecast1 = m.group(2) time2 = m.group(3) forecast2 = m.group(4) if DEBUG: print('time1, forecast1:', time1, forecast1) print('time2, forecast2:', time2, forecast2) send(' {}. {} = {}. {} = 30 +'.format(time1, forecast1, time2, forecast2))
from urllib.request import Request, urlopen import re import sys import time from pykob import internet, morse, kob, log import pykob # to access PyKOB version number VERSION = '1.0.7' WIRE = 106 IDTEXT = 'KOB Weather Service, AC' WPM = 20 # initial guess at received Morse speed #DEBUG = '~IACWXKSEA+' # run locally, don't connect to wire DEBUG = '' # run normally log.log('Starting Weather ' + VERSION) log.log('PyKOB version ' + pykob.VERSION) def readerCallback(char, spacing): global msg, bracket if spacing * 3 * myReader.dotLen > 20000 and char != '~': # dropped packet msg += ' QN ? QJ ' for i in range(0, len(char)): if char[i] == '[': msg += ' QN ' bracket = True elif char[i] == ']': msg += ' QJ ' bracket = False elif bracket:
""" """ audio module Provides audio for simulated sounder. """ import wave from pathlib import Path from pykob import log try: import pyaudio ok = True except: log.log('PyAudio not installed.') ok = False BUFFERSIZE = 16 nFrames = [0, 0] frames = [None, None] nullFrames = None iFrame = [0, 0] sound = 0 if ok: pa = pyaudio.PyAudio() # Resource folder root_folder = Path(__file__).parent resource_folder = root_folder / "resources" # Audio files
- display each character as it's sent SchedFeed 1.2 2016-01-11 - sort msgs by time and adjust for duplicate times SchedFeed 1.1 2015-12-30 - changed msgs element structure from list to tuple SchedFeed 1.0 2015-12-28 - initial release """ import time from pykob import config, kob, internet, morse, log log.log('SchedFeed 1.3') PORT = config.serial_port # serial port for KOB interface WPM = config.words_per_min_speed # code speed (words per minute) SOUND = config.sound # whether to enable computer sound for sounder WIRE = 199 # 0 for no feed to internet IDTEXT = 'Test feed, XX' # text to identify your feed, with office call msgs = [ # 24-hour clock, no leading zeros (822, '~ DS HN OS + ~ GA + ~ OS HN NO 18 D 822 HN + ~ OK DS +'), (1201, '~ DS NB OS + ~ GA + ~ OS NB NO 18 BY 1159 NB + ~ OK DS +'), (1528, '~ DS U OS + ~ GA + ~ OS U NO 18 BY 239 U + ~ OK DS +') ] # last entry ends with )] instead of ), msgs.sort(key=lambda m: m[0]) # sort messages by time for i in range(len(msgs) - 1): # adjust duplicate times
""" kob module Handles external key and/or sounder. """ import sys import threading import time from enum import Enum, IntEnum, unique from pykob import audio, config, log try: import serial serialAvailable = True except: log.log("pySerial not installed.") serialAvailable = False DEBOUNCE = 0.015 # time to ignore transitions due to contact bounce (sec) CODESPACE = 0.120 # amount of space to signal end of code sequence (sec) CKTCLOSE = 0.75 # length of mark to signal circuit closure (sec) if sys.platform == 'win32': from ctypes import windll windll.winmm.timeBeginPeriod(1) # set clock resoluton to 1 ms (Windows only) @unique class CodeSource(IntEnum): local = 1 wire = 2 player = 3