示例#1
0
def set_spacing(s):
    """Sets the Spacing (for Farnsworth timing) to None (disabled) `Spacing.none`,
    Character `Spacing.char` or Word `Spacing.word`

    When set to `Spacing.none` Farnsworth spacing will not be added.
    When set to `Spacing.char` Farnsworth spacing will be added between characters.
    When set to `Spacing.word` Farnsworth spacing will be added between words.

    Parameters
    ----------
    s : str
        The value `N|NONE` will set the spacing to `Spacing.none` (disabled).
        The value `C|CHAR` will set the spacing to `Spacing.char`.
        The value `W|WORD` will set the spacing to `Spacing.word`.
    """

    global spacing
    s = s.upper()
    if s == "N" or s == "NONE":
        spacing = Spacing.none
    elif s == "C" or s == "CHAR" or s == "CHARACTER":
        spacing = Spacing.char
    elif s == "W" or s == "WORD":
        spacing = Spacing.word
    else:
        msg = "SPACING value '{}' is not a valid `Spacing` value of 'NONE', 'CHAR' or 'WORD'.".format(
            s)
        log.err(msg)
        raise ValueError(msg)
    user_config.set(__CONFIG_SECTION, __SPACING_KEY, spacing.name.upper())
示例#2
0
def set_min_char_speed(s):
    """Sets the minimum character speed in words per minute

    A difference between character speed (in WPM) and text speed
    (in WPM) is used to calulate a Farnsworth timing value.

    This is the minimum character speed. If the text speed is
    higher, then the character speed will be bumped up to
    the text speed.

    Parameters
    ----------
    s : str
        The speed in words-per-minute as an interger string value
    """

    global min_char_speed
    try:
        _speed = int(s)
        min_char_speed = _speed
        user_config.set(__CONFIG_SECTION, __MIN_CHAR_SPEED_KEY,
                        str(min_char_speed))
    except ValueError as ex:
        log.err(
            "CHARS value '{}' is not a valid integer value. Not setting CWPM value."
            .format(ex.args[0]))
        raise
示例#3
0
def getArticles(url):
    if url[:7] == 'file://':
        s = open(os.getcwd() + '/' + url[7:]).read()
    else:
        retry = True
        while retry:
            try:
                s = urlopen(url).read().decode('utf-8')
                retry = False
            except:
                log.err('Can\'t open {}.'.format(url))
                time.sleep(5)
    articles = re.findall('<item>.*?</item>', s, re.IGNORECASE + re.DOTALL)
    for i in range(0, len(articles)):
        title, description, pubDate = None, None, None
        m = re.search('<title>(<!\[CDATA\[)?(.*?)(\]\]>)?</title>',
                      articles[i], re.IGNORECASE + re.DOTALL)
        if m:
            title = m.group(2)
        m = re.search('<description>(<!\[CDATA\[)?(.*?)(\]\]>)?</description>',
                      articles[i], re.IGNORECASE + re.DOTALL)
        if m:
            description = m.group(2)
            flags = re.IGNORECASE + re.DOTALL
            description = re.sub('&lt;.*?&gt;', '', description, 0, flags)
            description = re.sub('&amp;#039;', "'", description, 0, flags)
            description = re.sub('&amp;.*?;', ' ', description, 0, flags)
        m = re.search('<pubDate>(.*?)</pubDate>', articles[i],
                      re.IGNORECASE + re.DOTALL)
        if m:
            pubDate = m.group(1)
        articles[i] = title, description, pubDate
    return articles
示例#4
0
def set_interface_type(s):
    """Sets the Interface Type (for Key-Sounder, Loop or Keyer)

    Parameters
    ----------
    s : str
        The value `KS|KEY_SOUNDER` will set the interface type to 'InterfaceType.key_sounder'.
        The value `L|LOOP` will set the interface type to 'InterfaceType.loop'.
        The value `K|KEYER` will set the interface type to 'InterfaceType.keyer'.
    """

    global interface_type
    s = s.upper()
    if s == "KS" or s == "KEY_SOUNDER":
        interface_type = InterfaceType.key_sounder
    elif s == "L" or s == "LOOP":
        interface_type = InterfaceType.loop
    elif s == "K" or s == "KEYER":
        interface_type = InterfaceType.keyer
    else:
        msg = "TYPE value '{}' is not a valid `Interface Type` value of 'KEY_SOUNDER', 'LOOP' or 'KEYER'.".format(
            s)
        log.err(msg)
        raise ValueError(msg)
    user_config.set(__CONFIG_SECTION, __INTERFACE_TYPE_KEY,
                    interface_type.name.upper())
示例#5
0
def set_auto_connect(s):
    """Sets the Auto Connect to wire enable state

    When set to `True` via a value of "TRUE"/"ON"/"YES" the application should 
    automatically connect to the configured wire.

    Note that this is a 'suggestion'. It isn't used by the base pykob 
    modules. It should be used by applications (like MKOB) to initiate a connection 
    to the configured wire.
    
    Parameters
    ----------
    s : str
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE` 
        will enable auto-connect. Values of `NO`|`OFF`|`FALSE` will disable auto-connect.
    """

    global auto_connect
    try:
        auto_connect = strtobool(str(s))
        user_config.set(__CONFIG_SECTION, __AUTO_CONNECT_KEY,
                        onOffFromBool(auto_connect))
    except ValueError as ex:
        log.err(
            "Auto Connect value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#6
0
def callback(in_data, frame_count, time_info, status_flags):
    if frame_count != BUFFERSIZE:
        log.err('Unexpected frame count request from PyAudio:', frame_count)
    if iFrame[sound] + frame_count < nFrames[sound]:
        startByte = iFrame[sound] * frameWidth
        endByte = (iFrame[sound] + frame_count) * frameWidth
        outData = frames[sound][startByte:endByte]
        iFrame[sound] += frame_count
        return (outData, pyaudio.paContinue)
    else:
        return (nullFrames, pyaudio.paContinue)
示例#7
0
文件: kob.py 项目: Shadow2718/PyKOB
 def setSounder(self, state):
     try:
         if state != self.sdrState:
             self.sdrState = state
             if state:
                 if self.port:
                     self.port.rts = True
                 if self.audio:
                     audio.play(1)  # click
             else:
                 if self.port:
                     self.port.rts = False
                 if self.audio:
                     audio.play(0)  # clack
     except(OSError):
         log.err("Port not available.")
         self.port = None
示例#8
0
def set_wire(w: str):
    """Sets the wire to connect to

    Parameters
    ----------
    w : str
        The Wire number
    """

    global wire
    try:
        _wire = int(w)
        wire = _wire
        user_config.set(__CONFIG_SECTION, __WIRE_KEY, str(wire))
    except ValueError as ex:
        log.err("Wire number value '{}' is not a valid integer value.".format(
            ex.args[0]))
        raise
示例#9
0
def set_text_speed(s):
    """Sets the Text (code) speed in words per minute

    Parameters
    ----------
    s : str
        The text speed in words-per-minute as an interger string value
    """

    global text_speed
    try:
        _speed = int(s)
        text_speed = _speed
        user_config.set(__CONFIG_SECTION, __TEXT_SPEED_KEY, str(text_speed))
    except ValueError as ex:
        log.err("Text speed value '{}' is not a valid integer value.".format(
            ex.args[0]))
        raise
示例#10
0
def set_local(l):
    """Enable/disable local copy

    When local copy is enabled, the local sound/sounder configuration is
    used to locally sound the content being sent to the wire.

    Parameters
    ----------
    l : str
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE`
        will enable local copy. Values of `NO`|`OFF`|`FALSE` will disable local copy.
    """

    global local
    try:
        local = strtobool(str(l))
        user_config.set(__CONFIG_SECTION, __LOCAL_KEY, onOffFromBool(local))
    except ValueError as ex:
        log.err(
            "LOCAL value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#11
0
def set_code_type(s):
    """Sets the Code Type (for American or International)

    Parameters
    ----------
    s : str
        The value `A|AMERICAN` will set the code type to 'American'.
        The value `I|INTERNATIONAL` will set the code type to 'International'.
    """

    global code_type
    s = s.upper()
    if s == "A" or s == "AMERICAN":
        code_type = CodeType.american
    elif s == "I" or s == "INTERNATIONAL":
        code_type = CodeType.international
    else:
        msg = "TYPE value '{}' is not a valid `Code Type` value of 'AMERICAN' or 'INTERNATIONAL'.".format(
            s)
        log.err(msg)
        raise ValueError(msg)
    user_config.set(__CONFIG_SECTION, __CODE_TYPE_KEY, code_type.name.upper())
示例#12
0
def set_sound(s):
    """Sets the Sound/Audio enable state

    When set to `True` via a value of "TRUE"/"ON"/"YES" the computer audio
    will be used to produce sounder output.

    Parameters
    ----------
    s : str
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE`
        will enable sound. Values of `NO`|`OFF`|`FALSE` will disable sound.
    """

    global sound
    try:
        sound = strtobool(str(s))
        user_config.set(__CONFIG_SECTION, __SOUND_KEY, onOffFromBool(sound))
    except ValueError as ex:
        log.err(
            "SOUND value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#13
0
def set_remote(r):
    """Enable/disable remote send

    When remote send is enabled, the content will be sent to the
    wire configured.

    Parameters
    ----------
    r : str
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE`
        will enable remote send. Values of `NO`|`OFF`|`FALSE` will disable remote send.
    """

    global remote
    try:
        remote = strtobool(str(r))
        user_config.set(__CONFIG_SECTION, __REMOTE_KEY, onOffFromBool(remote))
    except ValueError as ex:
        log.err(
            "REMOTE value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#14
0
文件: kob.py 项目: Shadow2718/PyKOB
 def key(self):
     code = ()
     while self.port:
         try:
             s = self.port.dsr if not config.invert_key_input else not self.port.dsr # invert for RS-323 modem signal
         except(OSError):
             log.err("Port not available.")
             self.port = None
             return ""
         t = time.time()
         if s != self.keyState:
             self.keyState = s
             dt = int((t - self.tLastKey) * 1000)
             self.tLastKey = t
             if self.interfaceType == config.interface_type.key_sounder:
                 self.setSounder(s)
             time.sleep(DEBOUNCE)
             if s:
                 code += (-dt,)
             elif self.cktClose:
                 code += (-dt, +2)  # unlatch closed circuit
                 self.cktClose = False
                 return code
             else:
                 code += (dt,)
         if not s and code and \
                 t > self.tLastKey + CODESPACE:
             return code
         if s and not self.cktClose and \
                 t > self.tLastKey + CKTCLOSE:
             code += (+1,)  # latch circuit closed
             self.cktClose = True
             return code
         if len(code) >= 50:  # code sequences can't have more than 50 elements
             return code
         time.sleep(0.001)
     return ""
示例#15
0
文件: kob.py 项目: Shadow2718/PyKOB
 def __init__(
         self, port=None, interfaceType=config.interface_type.loop,
         audio=False, callback=None):
     self.t0 = -1.0  ### ZZZ Keep track of when the playback started
     self.callback = callback
     if port and serialAvailable:
         try:
             self.port = serial.Serial(port)
             self.port.dtr = True
         except:
             log.info("Interface for key and/or sounder on serial port '{}' not available. Key and sounder will not be used.".format(port))
             self.port = None
             self.callback = None
     else:
         self.port = None
         self.callback = None
     self.audio = audio
     self.interfaceType = interfaceType
     self.sdrState = False  # True: mark, False: space
     self.tLastSdr = time.time()  # time of last sounder transition
     self.setSounder(True)
     time.sleep(0.5)  # ZZZ Why is this here?
     if self.port:
         try:
             self.keyState = self.port.dsr if not config.invert_key_input else not self.port.dsr  # True: closed, False: open
             self.tLastKey = time.time()  # time of last key transition
             self.cktClose = self.keyState  # True: circuit latched closed
             if self.interfaceType == config.interface_type.key_sounder:
                 self.setSounder(self.keyState)
         except(OSError):
             log.err("Port not available.")
             self.port = None
     self.recorder = None
     if self.callback:
         keyreadThread = threading.Thread(name='KOB-KeyRead', daemon=True, target=self.callbackRead)
         keyreadThread.start()
示例#16
0
def set_invert_key_input(b):
    """
    Enable/disable key input signal (DSR) invert.

    When key-invert is enabled, the key input (DSR on the serial interface)
    is inverted (because the RS-232 logic is inverted). This is primarily used
    when the input is from a modem (in dial-up connection).

    Parameters
    ----------
    b : string 'true/false'
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE`
        will enable key invert. Values of `NO`|`OFF`|`FALSE` will disable key invert.
    """
    global invert_key_input
    try:
        invert_key_input = strtobool(str(b))
        user_config.set(__CONFIG_SECTION, __INVERT_KEY_INPUT_KEY,
                        onOffFromBool(invert_key_input))
    except ValueError as ex:
        log.err(
            "INVERT KEY INPUT value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#17
0
def set_sounder(s):
    """Sets the Sounder enable state

    When set to `True` via a value of "TRUE"/"ON"/"YES" the sounder will
    be driven if the `port` value is configured.

    Parameters
    ----------
    s : str
        The enable/disable state to set as a string. Values of `YES`|`ON`|`TRUE`
        will enable sounder output. Values of `NO`|`OFF`|`FALSE` will disable
        sounder output.
    """

    global sounder
    try:
        sounder = strtobool(str(s))
        user_config.set(__CONFIG_SECTION, __SOUNDER_KEY,
                        onOffFromBool(sounder))
    except ValueError as ex:
        log.err(
            "SOUNDER value '{}' is not a valid boolean value. Not setting value."
            .format(ex.args[0]))
        raise
示例#18
0
文件: Feed.py 项目: Shadow2718/PyKOB
    # The code speed for the feed:
    wpm = args.speed

    # The cwpm:
    cwpm = args.min_char_speed

    # Code type: American or International
    args_code_type = args.code_type.upper()
    if args_code_type == "A" or args_code_type == "AMERICAN":
        code_type = config.CodeType.american
    elif args_code_type == "I" or args_code_type == "INTERNATIONAL":
        code_type = config.CodeType.international
    else:
        msg = "TYPE value '{}' is not a valid `Code Type` value of 'AMERICAN' or 'INTERNATIONAL'.".format(
            s)
        log.err(msg)
        raise ValueError(msg)

    # Pause between articles (in seconds):
    artPause = args.artPause

    # Default group pause to article pause value if no group pause value is supplied
    grpPause = args.grpPause if args.grpPause > 0.0 else args.artPause

    # Number of days (from today) of articles to read before repeating:
    days = args.days

    # The wait time (in seconds) after someone else transmits before resuming feed:
    wait = args.wait

    playback_finished = threading.Event()
示例#19
0
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))
示例#20
0
    myInternet = internet.Internet(IDTEXT)
    myInternet.connect(WIRE)
    myReader = morse.Reader(callback=readerCallback)
    mySender = morse.Sender(WPM)
    myKOB = kob.KOB(port=None, audio=False)
    myReader.setWPM(WPM)
    code = []
    bracket = False
    msg = ''
    while True:
        try:
            code += myInternet.read()
            if code[-1] == 1:
                log.log('Weather.py: {}'.format(code))
                myReader.decode(code)
                myReader.flush()
                code = []
                bracket = False
                msg = ''
        except:
            log.err('Weather.py: Recovering from fatal error.')
            time.sleep(30)
            code = []
            bracket = False
            msg = ''
except KeyboardInterrupt:
    print()
    sys.exit(
        0
    )  # Since the main program is an infinite loop, ^C is a normal, successful exit.
示例#21
0
def read_config():
    """Read the configuration values from the user and machine config files.
    """

    global hostname
    global platform_name
    global os_name
    global pykob_version
    global python_version
    global pyaudio_version
    global pyserial_version
    global system_name
    global system_version
    global app_config
    global app_config_file_path
    global user_config
    global user_config_file_path
    global user_home
    global user_name
    #
    global serial_port
    #
    global auto_connect
    global code_type
    global interface_type
    global invert_key_input
    global local
    global min_char_speed
    global remote
    global server_url
    global sound
    global sounder
    global spacing
    global station
    global wire
    global text_speed

    # Get the system data
    try:
        user_name = getpass.getuser()
        user_home = os.path.expanduser('~')
        os_name = os.name
        system_name = platform.system()
        system_version = platform.release()
        platform_name = sys.platform
        pykob_version = pykob.VERSION
        python_version = "{}.{}.{}".format(sys.version_info.major,
                                           sys.version_info.minor,
                                           sys.version_info.micro)
        try:
            import pyaudio
            pyaudio_version = pyaudio.__version__  # NOTE: Using '__" property - not recommended, but only way to get version
        except:
            pyaudio_version = "PyAudio is not installed or the version information is not available (check installation)"
        try:
            import serial
            pyserial_version = serial.VERSION
        except:
            pyserial_version = "PySerial is not installed or the version information is not available (check installation)"
        hostname = socket.gethostname()

        # User configuration file name
        userConfigFileName = "config-{}.ini".format(user_name)
        app_configFileName = "config_app.ini"

        # Create the user and application configuration paths
        if system_name == "Windows":
            user_config_file_path = os.path.join(
                os.environ["LOCALAPPDATA"],
                os.path.normcase(os.path.join(__APP_NAME, userConfigFileName)))
            app_config_file_path = os.path.join(
                os.environ["ProgramData"],
                os.path.normcase(os.path.join(__APP_NAME, app_configFileName)))
        elif system_name == "Linux" or system_name == "Darwin":  # Linux or Mac
            user_config_file_path = os.path.join(
                user_home,
                os.path.normcase(
                    os.path.join(".{}".format(__APP_NAME),
                                 userConfigFileName)))
            app_config_file_path = os.path.join(
                user_home,
                os.path.normcase(
                    os.path.join(".{}".format(__APP_NAME),
                                 app_configFileName)))
        else:
            log.err("Unknown System name")
            exit

    except KeyError as ex:
        log.err("Key '{}' not found in environment.".format(ex.args[0]))
        exit

    create_config_files_if_needed()

    user_config_defaults = {\
        __AUTO_CONNECT_KEY:"OFF", \
        __CODE_TYPE_KEY:"AMERICAN", \
        __INTERFACE_TYPE_KEY:"LOOP", \
        __INVERT_KEY_INPUT_KEY:"OFF", \
        __LOCAL_KEY:"ON", \
        __MIN_CHAR_SPEED_KEY:"18", \
        __REMOTE_KEY:"ON", \
        __SERVER_URL_KEY:"NONE", \
        __SOUND_KEY:"ON", \
        __SOUNDER_KEY:"OFF", \
        __SPACING_KEY:"NONE", \
        __STATION_KEY:"", \
        __WIRE_KEY:"", \
        __TEXT_SPEED_KEY:"18"}
    app_config_defaults = {"PORT": ""}

    user_config = configparser.ConfigParser(defaults=user_config_defaults,
                                            allow_no_value=True,
                                            default_section=__CONFIG_SECTION)
    app_config = configparser.ConfigParser(defaults=app_config_defaults,
                                           allow_no_value=True,
                                           default_section=__CONFIG_SECTION)

    user_config.read(user_config_file_path)
    app_config.read(app_config_file_path)

    try:
        # Get the System (App) config values
        serial_port = app_config.get(__CONFIG_SECTION, __SERIAL_PORT_KEY)
        # If there isn't a PORT value set PORT to None
        if not serial_port:
            serial_port = None

        # Get the User config values
        __option = "Auto Connect to Wire"
        __key = __AUTO_CONNECT_KEY
        auto_connect = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Code type"
        __key = __CODE_TYPE_KEY
        _code_type = (user_config.get(__CONFIG_SECTION, __key)).upper()
        if _code_type == "AMERICAN":
            code_type = CodeType.american
        elif _code_type == "INTERNATIONAL":
            code_type = CodeType.international
        else:
            raise ValueError(_code_type)
        __option = "Interface type"
        __key = __INTERFACE_TYPE_KEY
        _interface_type = (user_config.get(__CONFIG_SECTION, __key)).upper()
        if _interface_type == "KEY_SOUNDER":
            interface_type = InterfaceType.key_sounder
        elif _interface_type == "LOOP":
            interface_type = InterfaceType.loop
        elif _interface_type == "KEYER":
            interface_type = InterfaceType.keyer
        else:
            raise ValueError(_interface_type)
        __option = "Invert key input"
        __key = __INVERT_KEY_INPUT_KEY
        invert_key_input = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Local copy"
        __key = __LOCAL_KEY
        local = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Minimum character speed"
        __key = __MIN_CHAR_SPEED_KEY
        min_char_speed = user_config.getint(__CONFIG_SECTION, __key)
        __option = "Remote send"
        __key = __REMOTE_KEY
        remote = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Text speed"
        __key = __TEXT_SPEED_KEY
        text_speed = user_config.getint(__CONFIG_SECTION, __key)
        __option = "Server URL"
        __key = __SERVER_URL_KEY
        _server_url = user_config.get(__CONFIG_SECTION, __key)
        if (not _server_url) or (_server_url.upper() != "NONE"):
            server_url = _server_url
        __option = "Sound"
        __key = __SOUND_KEY
        sound = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Sounder"
        __key = __SOUNDER_KEY
        sounder = user_config.getboolean(__CONFIG_SECTION, __key)
        __option = "Spacing"
        __key = __SPACING_KEY
        _spacing = (user_config.get(__CONFIG_SECTION, __key)).upper()
        if _spacing == "NONE":
            spacing = Spacing.none
        elif _spacing == "CHAR":
            spacing = Spacing.char
        elif _spacing == "WORD":
            spacing = Spacing.word
        else:
            raise ValueError(_spacing)
        __option = "Station"
        __key = __STATION_KEY
        _station = user_config.get(__CONFIG_SECTION, __key)
        if (not _station) or (_station.upper() != "NONE"):
            station = _station
        __option = "Wire"
        __key = __WIRE_KEY
        _wire = user_config.get(__CONFIG_SECTION, __key)
        if (_wire) or (_wire.upper() != "NONE"):
            try:
                wire = int(_wire)
            except ValueError as ex:
                # log.err("Wire number value '{}' is not a valid integer value.".format(_wire))
                wire = 1
    except KeyError as ex:
        log.err("Key '{}' not found in configuration file.".format(ex.args[0]))
        raise
    except ValueError as ex:
        log.err("{} option value '{}' is not a valid value. INI file key: {}.".
                format(__option, ex.args[0], __key))
        raise
示例#22
0
    def playback_start(self, list_data=False, max_silence=0, speed_factor=100):
        """
        Play a recording to the configured sounder.
        """
        self.playback_stop()
        self.__playback_resume_flag.clear()
        self.__playback_stop_flag.clear()

        self.__p_fts = -1
        self.__p_lts = 0
        self.__p_stations.clear()
        self.__p_fpts_index = []
        self.__p_line_no = 0
        self.__p_lines = 0
        self.__recorder_station_id = None
        self.__recorder_wire = None
        self.__list_data = list_data
        self.__max_silence = max_silence
        self.__speed_factor = speed_factor
        #
        # Get information from the current playback recording file.
        with open(self.__source_file_path, "r") as fp:
            self.__p_fpts_index.append(
                (0, 0,
                 False))  # Store line 0 as Time=0, Pos=0, Sender-Change=False
            previous_station = None
            # NOTE: Can't iterate over the file lines as it disables `tell()` and `seek()`.
            line = fp.readline()
            while line:
                try:
                    fpos = fp.tell()
                    data = json.loads(line)
                    ts = data['ts']
                    wire = data['w']
                    station = data['s']
                    ts = data['ts']
                    station = data['s']
                    # Store the file position and timestamp in the index to use
                    # for seeking to a line based on time or line number
                    self.__p_fpts_index.append(
                        (ts, fpos, station != previous_station))
                    previous_station = station
                    # Get the first and last timestamps from the recording
                    if self.__p_fts == -1 or ts < self.__p_fts:
                        self.__p_fts = ts  # Set the 'first' timestamp
                    if self.__p_lts < ts:
                        self.__p_lts = ts
                    # Update the number of lines
                    self.__p_lines += 1
                    # Generate the station list from the recording
                    self.__p_stations.add(station)
                    # Read the next line
                    line = fp.readline()
                except Exception as ex:
                    log.err(
                        "Error processing recording file: '{}' Line: {} Error: {}"
                        .format(self.__source_file_path, self.__p_line_no, ex))
                    return
        # Calculate recording file values to aid playback functions
        self.__playback_thread = threading.Thread(
            name='Recorder-Playback-Play',
            daemon=True,
            target=self.callbackPlay)
        self.__playback_thread.start()
        if self.__play_station_list_callback:
            self.__p_stations_thread = threading.Thread(
                name='Recorder-Playback-StationList',
                daemon=True,
                target=self.callbackPlayStationList)
            self.__p_stations_thread.start()
        if self.__list_data:
            # Print some values about the recording
            print(" Lines: {}  Start: {}  End: {}  Duration: {}".format(
                self.__p_lines, date_time_from_ts(self.__p_fts),
                date_time_from_ts(self.__p_lts),
                hms_from_ts(self.__p_lts, self.__p_fts)))
示例#23
0
                    help='file (in MorseKOB recorder format) to be played back.')
    arg_parser.add_argument("--list", action="store_true", default=False, help="Display the recorded data as it is played.", dest="listData")
    arg_parser.add_argument("--speedfactor", type=int, metavar="n", default=100, help="Factor (percentage) to adjust playback speed by (Default 100).", dest="speedFactor")
    arg_parser.add_argument("--maxsilence", type=int, metavar="n", default=5, help="Longest silence duration to play, in seconds. A value of '0' will reproduce all silence as recorded (Defalut 5).", dest="maxSilence")
    args = arg_parser.parse_args()
    
    interface_type = args.interface_type
    port = args.serial_port # serial port for KOB/sounder interface
    sound = strtobool(args.sound)
    sounder = strtobool(args.sounder)
    playback_file = args.playback_file

    # Validate that the file can be opened
    try:
        fp = open(playback_file, 'r')
        fp.close()
    except FileNotFoundError:
        log.err("Recording file not found: {}".format(playback_file))

    myKOB = kob.KOB(port=port, audio=sound, interfaceType=interface_type)

    myRecorder = recorder.Recorder(None, playback_file, play_code_callback=callbackPlay, play_finished_callback=callbackPlayFinished, station_id="Player")
    myRecorder.playback_start(list_data=args.listData, max_silence=args.maxSilence, speed_factor=args.speedFactor)
    # Wait until playback is finished
    while not playback_finished.is_set():
        time.sleep(0.5)
except KeyboardInterrupt:
    print("\nEarly exit.")
    myRecorder.playback_stop()
    sys.exit(0)     # ^C is considered a normal exit.