def __init__(self, **params): super().__init__() self.id = 'chT' self.params = params portname = params.get('portname', '/dev/ttyUSB0') baudrate = params.get('baudrate', 50) bytesize = params.get('bytesize', 5) stopbits = params.get('stopbits', serial.STOPBITS_ONE_POINT_FIVE) coding = params.get('coding', 0) loopback = params.get('loopback', None) self._local_echo = params.get('loc_echo', False) self._rx_buffer = [] self._tx_buffer = [] self._counter_LTRS = 0 self._counter_FIGS = 0 self._counter_dial = 0 self._time_last_dial = 0 self._cts_stable = True # rxd=Low self._cts_counter = 0 self._time_squelch = 0 self._is_enabled = False self._is_online = False self._last_out_waiting = 0 self._set_mode(params['mode']) if loopback is not None: self._loopback = loopback self._inverse_dtr = params.get('inverse_dtr', self._inverse_dtr) self._inverse_rts = params.get('inverse_rts', self._inverse_rts) # init serial self._tty = serial.Serial(portname, write_timeout=0) if baudrate not in self._tty.BAUDRATES: raise Exception('Baudrate not supported') if bytesize not in self._tty.BYTESIZES: raise Exception('Databits not supported') if stopbits not in self._tty.STOPBITS: raise Exception('Stopbits not supported') self._tty.baudrate = baudrate self._tty.bytesize = bytesize self._tty.stopbits = stopbits self._baudrate = baudrate # init codec #character_duration = (bytesize + 1.0 + stopbits) / baudrate character_duration = ( bytesize + 3.0) / baudrate # CH340 sends always with 2 stop bits self._mc = txCode.BaudotMurrayCode( self._loopback, coding=coding, character_duration=character_duration) self._set_enable(False) self._set_online(False)
def read_file(self, file_name: str): base_name = os.path.join('read', file_name.lower()) try: name = self.read_file_exist(base_name, ('txt', )) text = '' if name: with open(name, mode="r", encoding="utf-8") as fp: text = fp.read() text = text.replace('\n', '\r\n') text = txCode.BaudotMurrayCode.translate(text) name = self.read_file_exist(base_name, ('pix', 'pox')) if name: with open(name, 'rb') as fp: text = fp.read().decode('ASCII', errors='ignore') for us, eu in (('&', '8'), ('#', 'M'), ('$', 'S'), ('"', "'"), (';', ','), ('!', '1'), ('\x1A', '')): text = text.replace(us, eu) text = txCode.BaudotMurrayCode.translate(text) if True: mc = txCode.BaudotMurrayCode() bintext = mc.encodeA2BM(text) with open(base_name + '_.bin', 'wb') as wfp: wfp.write(bintext) name = self.read_file_exist(base_name, ('bin', 'ls')) if name: with open(name, 'rb') as fp: bintext = fp.read() mc = txCode.BaudotMurrayCode(flip_bits=name.endswith('ls')) text = mc.decodeBM2A(bintext) if text: self._rx_buffer.extend(list(text)) l.info("Read file: {!r} ({} chars)".format(name, len(text))) except: l.error("Error in read file")
def __init__(self, **params): super().__init__() self._mc = txCode.BaudotMurrayCode() self.id = '=' self.params = params self._tx_buffer = [] self.run = True self._tx_thread = Thread(target=self.thread_tx) self._tx_thread.start()
def __init__(self, **params): super().__init__() self._mc = txCode.BaudotMurrayCode(loop_back=False) self.id = 'edS' self.params = params self._tx_buffer = [] self._rx_buffer = [] self._is_online = Event() self._ST_pressed = False # State of rx thread, governs most of the module operation. States: # - 0 offline / startup # - 10 going online by ESC-WB/-A # - 20 online # - 30 going offline by ESC-Z # - 40 offline delay after buffer is empty # - 50 offline, wait for A level self._rx_state = 0 # Helper variables for printer feedback self._last_tx_buf_len = 0 self._send_feedback = False self.recv_squelch = self.params.get('recv_squelch', 100) self.recv_debug = self.params.get('recv_debug', False) self.send_WB_pulse = self.params.get('send_WB_pulse', False) recv_f0 = self.params.get('recv_f0', 2250) recv_f1 = self.params.get('recv_f1', 3150) recv_f = [recv_f0, recv_f1] self._recv_decode_init(recv_f) # Save how many characters have been printed per session self.printed_chars = 0 self._run = True self._tx_thread = Thread(target=self.thread_tx, name='ED1000tx') self._tx_thread.start() self._rx_thread = Thread(target=self.thread_rx, name='ED1000rx') self._rx_thread.start()
def __init__(self, **params): super().__init__() self._mc = txCode.BaudotMurrayCode() self.id = '=' self.params = params self._txb_buffer = [] self._rxb_buffer = [] self._carrier_counter = 0 self._carrier_detected = False self.do_plot() self.run = True #self._tx_thread = Thread(target=self.thread_tx) #self._tx_thread.start() self._rx_thread = Thread(target=self.thread_rx) self._rx_thread.start()
def __init__(self, **params): super().__init__() self._mc = txCode.BaudotMurrayCode(loop_back=False) self.id = 'edS' self.params = params self._tx_buffer = [] self._rx_buffer = [] self._is_online = Event() self._ST_pressed = False # State of rx thread, governs most of the module operation (see class # ST) self._rx_state = ST.OFFLINE # Helper variables for printer feedback self._last_tx_buf_len = 0 self._send_feedback = False self.recv_squelch = self.params.get('recv_squelch', 100) self.recv_debug = self.params.get('recv_debug', False) self.send_WB_pulse = self.params.get('send_WB_pulse', False) self.unres_threshold = self.params.get('unres_threshold', 100) recv_f0 = self.params.get('recv_f0', 2250) recv_f1 = self.params.get('recv_f1', 3150) recv_f = [recv_f0, recv_f1] self._recv_decode_init(recv_f) # Save how many characters have been printed per session self.printed_chars = 0 # Track MCP active state for printer start feedback self._MCP_active = False self._run = True self._tx_thread = Thread(target=self.thread_tx, name='ED1000tx') self._tx_thread.start() self._rx_thread = Thread(target=self.thread_rx, name='ED1000rx') self._rx_thread.start()
def __init__(self, **params): super().__init__() self._mc = txCode.BaudotMurrayCode(loop_back=False) self.id = '=' self.params = params self._tx_buffer = [] self._rx_buffer = [] self._is_online = False recv_f0 = self.params.get('recv_f0', 2250) recv_f1 = self.params.get('recv_f1', 3150) recv_f = [recv_f0, recv_f1] self._recv_decode_init(recv_f) self.run = True self._tx_thread = Thread(target=self.thread_tx, name='ED1000tx') self._tx_thread.start() self._rx_thread = Thread(target=self.thread_rx, name='ED1000rx') self._rx_thread.start()
def process_connection(self, s: socket.socket, is_server: bool, is_ascii: bool): # Takes client socket as argument. """Handles a client or server connection.""" bmc = txCode.BaudotMurrayCode(False, False, True) sent_counter = 0 self._received_counter = 0 printed_counter = 0 timeout_counter = -1 time_next_send = None error = False s.settimeout(0.2) self._connected = ST.CON_INIT # Store remote protocol version to control negotiation self._remote_protocol_ver = None # Connection type hinting and detection if is_ascii is None: l.info('Connection hint: auto-detect enabled') elif is_ascii: l.info('Connection hint: ASCII connection') else: l.info('Connection hint: i-Telex connection') # New printer feedback based on ESC-~ # # Overview: # - i-Telex requires us to periodically send Acknowledge packets so # that the sending party can determine how much of the sent data has # been printed already. Its payload is an 8 bit monotonic counter of # undefined reference point. It should however be 0 as soon as we're # ready to receive and print data. # # - Basic function: We count data received from remote and subtract # current printer buffer contents. Special care is taken to keep the # counter monotonically increasing, which otherwise might happen if # other modules than us also send data to the printer. # If we're server, use negative Acknowledge counter first to allow for # fixed-length welcome banner printing self._acknowledge_counter = self._last_acknowledge_counter = ( -24 if is_server else 0 ) # fixed length of welcome banner, see txDevMCP # The rationale here is to, after starting the printer, first print the # complete welcome banner. Received data must only by printed *after* # this. # # The typical sequence is as follows: # # - After printable data is received for the first time, we decide on # the connection type (Baudot or ASCII), queue some commands (start # printer, MCP output welcome banner) and also queue the received # data afterwards. (state 2) # # - Main loop read()-s us. Our read method is filtered (based on state # 2) so that only commands are read, printable data is retained for # later perusal. # # - Eventually, MCP receives the welcome banner command. It sends the # banner, which is writ[e]()-ten to us. After the banner, it sends # the ESC-WELCOME command which tells us the banner has been written # completely. On this command, our read method is unlocked and # previously received data is available for main loop. (state 4) # Start with ST.DISCON to trigger log message _connected_before = ST.DISCON while self._connected > ST.DISCON: if _connected_before != self._connected: l.info("State transition: {!s}=>{!s}".format( _connected_before, self._connected)) _connected_before = self._connected # We just entered ST.CON_TP_RUN (printer running, waiting for # welcome banner) if self._connected == ST.CON_TP_RUN: if is_server: # Send welcome banner self._tx_buffer = [] self.send_welcome(s) else: # We're client: skip ST.CON_TP_RUN self._connected = ST.CON_FULL continue elif self._connected == ST.CON_FULL: # Send first Acknowledge if not is_ascii: # Send fixed value in Acknowledge packet, mainly for # server case (24 characters of welcome banner have to # be printed before anything else). Typically, the # welcome banner hasn't yet reached the printer buffer, # which would lead to sending 0 instead of -24. # # The next timed Acknowledge will be sent with a filled # printer buffer in most cases. If not, the damage # should be manageable. # # (This problem results from the non-deterministic # sequence with the current piTelex architecture, # namely multiple threads and message passing in a # central loop, and can be solved best by a major # restructuring.) self.send_ack( s, (-24 if is_server else 0 )) # fixed length of welcome banner, see txDevMCP try: data = s.recv(1) # piTelex terminates; close connection if not self._run: break # lost connection if not data: l.warning("Remote has closed connection") break # Telnet control sequence elif data[0] == 255: d = s.recv(2) # skip next 2 bytes from telnet command # i-Telex packet elif data[0] in allowed_types(): packet_error = False d = s.recv(1) data += d packet_len = d[0] if packet_len: data += s.recv(packet_len) # Heartbeat if data[0] == 0 and packet_len == 0: l.debug( 'Received i-Telex packet: Heartbeat ({})'.format( display_hex(data))) # Direct Dial elif data[0] == 1 and packet_len == 1: l.debug( 'Received i-Telex packet: Direct dial ({})'.format( display_hex(data))) # Disable emitting "direct dial" command, since it's # currently not acted upon anywhere. #self._rx_buffer.append('\x1bD'+str(data[2])) # Instead, only accept extension 0 (i-Telex default) # and None, and reject all others. ext = decode_ext_from_direct_dial(data[2]) l.info('Direct Dial, extension {}'.format(ext)) if not ext in ('0', None): self.send_reject(s, 'na') error = True break else: if self._connected == ST.CON_INIT: if not self._printer_running: # Request printer start; confirmation will # arrive as ESC-~ (write method will # advance to ST.CON_TP_RUN and do what's in # the following else block) self._connected = ST.CON_TP_REQ self._rx_buffer.append('\x1bA') else: # Printer already running; welcome banner # will be sent above in next iteration if # we're server self._connected = ST.CON_TP_RUN self._rx_buffer.append('\x1bA') # Baudot Data elif data[0] == 2 and packet_len >= 1 and packet_len <= 50: l.debug( 'Received i-Telex packet: Baudot data ({})'.format( display_hex(data))) aa = bmc.decodeBM2A(data[2:]) if self._connected == ST.CON_INIT: if not self._printer_running: # Request printer start; confirmation will # arrive as ESC-~ (write method will # advance to ST.CON_TP_RUN and do what's in # the following else block) self._connected = ST.CON_TP_REQ self._rx_buffer.append('\x1bA') else: # Printer already running; welcome banner # will be sent above in next iteration if # we're server self._connected = ST.CON_TP_RUN self._rx_buffer.append('\x1bA') for a in aa: if a == '@': a = '#' self._rx_buffer.append(a) self._received_counter += len(data[2:]) # Send Acknowledge if printer is running and we've got # at least 16 characters left to print if self._connected >= ST.CON_FULL and self._print_buf_len >= 16: self.send_ack(s, self._acknowledge_counter) # End elif data[0] == 3 and packet_len == 0: l.debug('Received i-Telex packet: End ({})'.format( display_hex(data))) l.info('End by remote') break # Reject elif data[0] == 4 and packet_len <= 20: l.debug('Received i-Telex packet: Reject ({})'.format( display_hex(data))) aa = data[2:].decode('ASCII', errors='ignore') # i-Telex may pad with \x00 (e.g. "nc\x00"); remove padding aa = aa.rstrip('\x00') l.info( 'i-Telex connection rejected, reason {!r}'.format( aa)) aa = bmc.translate(aa) for a in aa: self._rx_buffer.append(a) break # Acknowledge elif data[0] == 6 and packet_len == 1: l.debug( 'Received i-Telex packet: Acknowledge ({})'.format( display_hex(data))) # TODO: Fix calculation and prevent overflows, e.g. if # the first ACK is sent with a low positive value. This # might be done by saving the first ACK's absolute # counter value and only doing difference calculations # afterwards. unprinted = (sent_counter - int(data[2])) & 0xFF #if unprinted < 0: # unprinted += 256 l.debug( str(data[2]) + '/' + str(sent_counter) + '=' + str(unprinted) + " (printed/sent=unprinted)") if unprinted < 7: # about 1 sec time_next_send = None else: time_next_send = time.monotonic() + (unprinted - 6) * 0.15 # Send Acknowledge if printer is running and remote end # has printed all sent characters # ! Better not, this will create an Ack flood ! # if self._connected >= ST.CON_FULL and unprinted == 0: # self.send_ack(s, self._acknowledge_counter) # Send remote printer buffer feedback self._rx_buffer.append('\x1b^' + str(unprinted)) # Version elif data[0] == 7 and packet_len >= 1 and packet_len <= 20: l.debug('Received i-Telex packet: Version ({})'.format( display_hex(data))) if self._remote_protocol_ver is None: if data[2] != 1: # This is the first time an unsupported version was offered l.warning( "Unsupported version offered by remote ({}), requesting v1" .format(display_hex(data[2:]))) self.send_version(s) else: # Only send version packet in response to valid # version when we're server, because as client, # we sent a version packet directly after # connecting. if is_server: self.send_version(s) # Store offered version self._remote_protocol_ver = data[2] else: if data[2] != 1: # The remote station insists on incompatible # version. Send the not-officially-defined # error code "ver". l.error( "Unsupported version insisted on by remote ({})" .format(display_hex(data[2:]))) self.send_reject(s, 'ver') error = True break else: if data[2] != self._remote_protocol_ver: l.info( "Negotiated protocol version {}, initial request was {}" .format(data[2], self._remote_protocol_ver)) self._remote_protocol_ver = data[2] else: # Ignore multiple good version packets l.info("Redundant Version packet") # Self test elif data[0] == 8 and packet_len >= 2: l.debug( 'Received i-Telex packet: Self test ({})'.format( display_hex(data))) # Remote config elif data[0] == 9 and packet_len >= 3: l.info('Received i-Telex packet: Remote config ({})'. format(display_hex(data))) # Wrong packet - will resync at next socket.timeout else: l.warning('Received invalid i-Telex Packet: {}'.format( display_hex(data))) packet_error = True if not packet_error: if is_ascii is None: l.info('Detected i-Telex connection') is_ascii = False elif is_ascii: l.warning( 'Detected i-Telex connection, but ASCII was expected' ) is_ascii = False # Also send Acknowledge packet if triggered by idle function if self._send_acknowledge_idle: self._send_acknowledge_idle = False self.send_ack(s, self._acknowledge_counter) # ASCII character(s) else: l.debug('Received non-i-Telex data: {} ({})'.format( repr(data), display_hex(data))) if is_ascii is None: l.info('Detected ASCII connection') is_ascii = True elif not is_ascii: l.warning( 'Detected ASCII connection, but i-Telex was expected' ) is_ascii = True if self._connected == ST.CON_INIT: if not self._printer_running: # Request printer start; confirmation will # arrive as ESC-~ (write method will # advance to ST.CON_TP_RUN and do what's in # the following else block) self._connected = ST.CON_TP_REQ self._rx_buffer.append('\x1bA') else: # Printer already running; welcome banner # will be sent above in next iteration if # we're server self._connected = ST.CON_TP_RUN self._rx_buffer.append('\x1bA') data = data.decode('ASCII', errors='ignore').upper() data = txCode.BaudotMurrayCode.translate(data) for a in data: if a == '@': a = '#' self._rx_buffer.append(a) self._received_counter += 1 except socket.timeout: #l.debug('.') if is_server and self.printer_start_timed_out: self.printer_start_timed_out = False if is_ascii: s.sendall(b"der") else: self.send_reject(s, "der") l.error( "Disconnecting client because printer didn't start up") error = True break if is_ascii is not None: # either ASCII or baudot connection detected timeout_counter += 1 if is_ascii: if self._tx_buffer: sent = self.send_data_ascii(s) sent_counter += sent else: # baudot if (timeout_counter % 5) == 0: # every 1 sec # Send Acknowledge if printer is running if self._connected >= ST.CON_FULL: self.send_ack(s, self._acknowledge_counter) if self._tx_buffer: if time_next_send and time.monotonic( ) < time_next_send: l.debug('Sending paused for {:.3f} s'.format( time_next_send - time.monotonic())) pass else: sent = self.send_data_baudot(s, bmc) sent_counter += sent if sent > 7: time_next_send = time.monotonic() + ( sent - 6) * 0.15 elif (timeout_counter % 15) == 0: # every 3 sec #self.send_heartbeat(s) pass # Suppress Heartbeat for now # # Background: The spec and personal conversation # with Fred yielded that i-Telex uses Heartbeat # only until the printer has been started. After # that, only Acknowledge is used. # # Complications arise from the fact that some # services in the i-Telex network interpret # Heartbeat just like Acknowledge, i.e. printer is # started and printer buffer empty. Special case is # the 11150 service, which in the current version, # on receiving Heartbeat, sends a WRU whilst the # welcome banner is being printed, causing a # character jumble. except socket.error: l.error("Exception caught:", exc_info=sys.exc_info()) error = True break if not is_ascii: # Don't send end packet in case of error. There may be two error # cases: # - Protocol error: We've already sent a reject package. # - Network error: There's no connection to send over anymore. if not error: self.send_end(s) l.info('end connection') self._connected = ST.DISCON if _connected_before != self._connected: l.info("State transition: {!s}=>{!s}".format( _connected_before, self._connected))
def thread_srv_handle_client(self, client): # Takes client socket as argument. """Handles a single client connection.""" bmc = txCode.BaudotMurrayCode(False, False, True) is_ascii = None # not known yet client.settimeout(0.2) self._rx_buffer.append('\x1bA') while self.run: try: data = client.recv(1) if not data: # lost connection break elif data[0] < 0x10: # i-Telex packet if is_ascii is None: self.send_welcome(client) is_ascii = False d = client.recv(1) data += d plen = d[0] data += client.recv(plen) if data[0] == 0: # Heartbeat #LOG('Heartbeat '+repr(data), 4) pass elif data[0] == 1: # Direct Dial LOG('Direct Dial '+repr(data), 4) self._rx_buffer.append('\x1bD'+str(data[2])) elif data[0] == 2 and plen > 0: # Baudot data #LOG('Baudot data '+repr(data), 4) aa = bmc.decodeBM2A(data[2:]) for a in aa: if a == '@': a = '#' self._rx_buffer.append(a) self._received += len(data[2:]) self.send_ack(client) elif data[0] == 3: # End LOG('End '+repr(data), 4) break elif data[0] == 4: # Reject LOG('Reject '+repr(data), 4) break elif data[0] == 6 and plen == 1: # Acknowledge #LOG('Acknowledge '+repr(data), 4) LOG(str(data[2])) pass elif data[0] == 7 and plen >= 1: # Version #LOG('Version '+repr(data), 4) self.send_version(client) elif data[0] == 8: # Self test LOG('Self test '+repr(data), 4) pass elif data[0] == 9: # Remote config LOG('Remote config '+repr(data), 4) pass else: # ASCII character(s) #LOG('Other', repr(data), 4) if is_ascii is None: self.send_welcome(client) is_ascii = True data = data.decode('ASCII', errors='ignore').upper() data = txCode.BaudotMurrayCode.translate(data) for a in data: if a == '@': a = '#' self._rx_buffer.append(a) self._received += 1 except socket.timeout: #LOG('.', 4) if is_ascii is not None: if self._tx_buffer: if is_ascii: self.send_data_ascii(client) else: self.send_data_baudot(client, bmc) else: if not is_ascii: self.send_heartbeat(client) except socket.error: LOG('Error socket', 2) break LOG('end connection', 3) client.close() del self.clients[client] self._rx_buffer.append('\x1bZ') pass
def process_connection(self, s: socket.socket, is_server: bool, is_ascii: bool): # Takes client socket as argument. """Handles a client or server connection.""" bmc = txCode.BaudotMurrayCode(False, False, True) sent_counter = 0 received_counter = 0 timeout_counter = -1 time_next_send = None s.settimeout(0.2) self._connected = True while self._connected: try: data = s.recv(1) # lost connection if not data: break # Telnet control sequence elif data[0] == 255: d = s.recv(2) # skip next 2 bytes from telnet command # i-Telex packet elif data[0] < 10: packet_error = False d = s.recv(1) data += d packet_len = d[0] if packet_len: data += s.recv(packet_len) # Heartbeat if data[0] == 0 and packet_len == 0: #LOG('Heartbeat '+repr(data), 4) pass # Direct Dial elif data[0] == 1 and (1 <= packet_len <= 10): LOG('Direct Dial ' + repr(data), 4) if packet_len >= 5: id = (data[3] << 24) | (data[4] << 16) | ( data[5] << 8) | (data[6]) print(id) self._rx_buffer.append('\x1bD' + str(data[2])) self.send_ack(s, received_counter) # Baudot Data elif data[0] == 2 and packet_len >= 1 and packet_len <= 50: #LOG('Baudot data '+repr(data), 4) aa = bmc.decodeBM2A(data[2:]) for a in aa: if a == '@': a = '#' self._rx_buffer.append(a) received_counter += len(data[2:]) self.send_ack(s, received_counter) # End elif data[0] == 3 and packet_len == 0: LOG('End ' + repr(data), 4) break # Reject elif data[0] == 4 and packet_len <= 20: LOG('Reject ' + repr(data), 4) aa = bmc.translate(data[2:]) for a in aa: self._rx_buffer.append(a) break # Acknowledge elif data[0] == 6 and packet_len == 1: #LOG('Acknowledge '+repr(data), 4) unprinted = (sent_counter - int(data[2])) & 0xFF #if unprinted < 0: # unprinted += 256 LOG( str(data[2]) + '/' + str(sent_counter) + '=' + str(unprinted), 4) if unprinted < 7: # about 1 sec time_next_send = None else: time_next_send = time.time() + (unprinted - 6) * 0.15 pass # Version elif data[0] == 7 and packet_len >= 1 and packet_len <= 20: #LOG('Version '+repr(data), 4) if not is_server or data[2] != 1: self.send_version(s) # Self test elif data[0] == 8 and packet_len >= 2: LOG('Self test ' + repr(data), 4) pass # Remote config elif data[0] == 9 and packet_len >= 3: LOG('Remote config ' + repr(data), 4) pass # Wrong packet - will resync at next socket.timeout else: LOG('ERROR Packet ' + repr(data), 3) packet_error = True if not packet_error: is_ascii = False # ASCII character(s) else: #LOG('Other', repr(data), 4) is_ascii = True data = data.decode('ASCII', errors='ignore').upper() data = txCode.BaudotMurrayCode.translate(data) for a in data: if a == '@': a = '#' self._rx_buffer.append(a) received_counter += 1 except socket.timeout: #LOG('.', 4) if is_ascii is not None: # unknown if ASCII or baudot timeout_counter += 1 if is_server and timeout_counter == 1: self._tx_buffer = [] self.send_welcome(s) if is_ascii: if self._tx_buffer: sent = self.send_data_ascii(s) sent_counter += sent else: # baudot if (timeout_counter % 5) == 0: # every 1 sec self.send_ack(s, received_counter) if self._tx_buffer: if time_next_send and time.time() < time_next_send: LOG( 'Wait' + str(int(time_next_send - time.time())), 4) pass else: sent = self.send_data_baudot(s, bmc) sent_counter += sent if sent > 7: time_next_send = time.time() + (sent - 6) * 0.15 elif (timeout_counter % 15) == 0: # every 3 sec self.send_heartbeat(s) except socket.error: LOG('ERROR socket', 2) break if not is_ascii: self.send_end(s) LOG('end connection', 3) self._connected = False
def __init__(self, **params): super().__init__() self.id = 'piT' self.params = params self._timing_tick = 0 self._time_EOT = 0 self._last_waiting = 0 self._state = None self._time_squelch = 0 self._use_squelch = True self._keep_alive_counter = 0 self._tx_buffer = [] self._rx_buffer = [] # get setting params self._mode = params.get('mode', 'TW39') self._baudrate = params.get('baudrate', 50) self._bytesize = params.get('bytesize', 5) self._stopbits = params.get('stopbits', 1.5) self._stopbits2 = int(self._stopbits * 2 + 0.5) self._pin_txd = params.get('pin_txd', 17) #self._inv_txd = params.get('inv_txd', False) # not possible with PIGPIO self._pin_dir = params.get('pin_dir', 0) self._pin_rxd = params.get('pin_rxd', 27) self._inv_rxd = params.get('inv_rxd', False) self._pin_relay = params.get('pin_relay', 22) self._inv_relay = params.get('inv_relay', False) self._pin_power = params.get('pin_power', 0) self._inv_power = params.get('inv_power', False) self._pin_number_switch = params.get( 'pin_number_switch', params.get('pin_fsg_ns', 6)) # pin typical wired to rxd pin self._inv_number_switch = params.get('inv_number_switch', False) self._line_observer = None if params.get('use_observe_line', True): self._pin_observe_line = params.get('pin_observe_line', self._pin_rxd) self._inv_observe_line = params.get('inv_observe_line', self._inv_rxd) self._line_observer = Observer(self._pin_observe_line, self._inv_observe_line, 10) # 10ticks = 0.5sec self._coding = params.get('coding', 0) self._loopback = params.get('loopback', True) self._timing_rxd = params.get('timing_rxd', False) self._WB_pulse_length = params.get('WB_pulse_length', 40) self._double_WR = params.get('double_WR', False) # init codec self._character_duration = (self._bytesize + 1.0 + self._stopbits) / self._baudrate self._mc = txCode.BaudotMurrayCode( self._loopback, coding=self._coding, character_duration=self._character_duration) # init GPIOs pi.set_mode(self._pin_rxd, pigpio.INPUT) pi.set_pull_up_down(self._pin_rxd, pigpio.PUD_UP) pi.set_glitch_filter(self._pin_rxd, 50000 // self._baudrate) # 1ms @ 50Bd self._number_switch = None if self._pin_number_switch > 0: # 0:keyboard pos:TW39 neg:TW39@RPiCtrl self._number_switch = NumberSwitch(self._pin_number_switch, self._callback_number_switch, self._inv_number_switch) pi.set_mode(self._pin_txd, pigpio.OUTPUT) #pi.write(self._pin_txd, not self._inv_txd) pi.write(self._pin_txd, 1) if self._pin_power: pi.set_mode(self._pin_power, pigpio.OUTPUT) pi.write(self._pin_power, self._inv_power) if self._pin_relay: pi.set_mode(self._pin_relay, pigpio.OUTPUT) # relay for commutating pi.write(self._pin_relay, self._inv_relay) # pos polarity if self._pin_dir: pi.set_mode(self._pin_dir, pigpio.OUTPUT) # direction of comminication pi.write(self._pin_dir, 0) # 1=transmitting # init bit bongo serial read try: _ = pi.bb_serial_read_close( self._pin_rxd ) # try to close if it is still open from last debug except: pass _ = pi.bb_serial_read_open(self._pin_rxd, self._baudrate, self._bytesize) pi.bb_serial_invert(self._pin_rxd, self._inv_rxd) if self._timing_rxd: self._cb = pi.callback(self._pin_rxd, pigpio.EITHER_EDGE, self._callback_timing) # init bit bongo serial write self.last_wid = None # init state self._set_state(S_OFFLINE)
def __init__(self, **params): super().__init__() self._tx_buffer = [] self._rx_buffer = [] self._cb = None self._is_pulse_dial = False self._pulse_dial_count = 0 self.id = '#' self.params = params self._baudrate = params.get('baudrate', 50) self._bytesize = params.get('bytesize', 5) self._stopbits = params.get('stopbits', 1.5) self._pin_txd = params.get('pin_txd', 17) self._pin_rxd = params.get('pin_rxd', 27) self._pin_rel = params.get('pin_rel', 22) self._pin_dir = params.get('pin_dir', 11) #self._pin_oin = params.get('pin_oin', 10) self._pin_opt = params.get('pin_opt', 9) #self._pin_sta = params.get('pin_sta', 12) self._inv_rxd = params.get('inv_rxd', False) #self._inv_txd = params.get('inv_txd', False) self._loopback = params.get('loopback', True) self._uscoding = params.get('uscoding', True) # init codec character_duration = (self._bytesize + 1.0 + self._stopbits) / self._baudrate self._mc = txCode.BaudotMurrayCode( self._loopback, us_coding=self._uscoding, character_duration=character_duration) # init GPIOs pi.set_pad_strength(0, 8) pi.set_mode(self._pin_rxd, pigpio.INPUT) pi.set_pull_up_down(self._pin_rxd, pigpio.PUD_UP) pi.set_mode(self._pin_txd, pigpio.OUTPUT) #pi.write(self._pin_txd, not self._inv_txd) pi.write(self._pin_txd, 1) pi.set_mode(self._pin_opt, pigpio.OUTPUT) pi.write(self._pin_opt, 0) pi.set_mode(self._pin_rel, pigpio.OUTPUT) # relais for commutating pi.write(self._pin_rel, 0) # pos polarity pi.set_mode(self._pin_dir, pigpio.OUTPUT) # direction of comminication pi.write(self._pin_dir, 0) # 1=transmitting # init bit bongo serial read pi.set_glitch_filter(self._pin_rxd, 1000) # 1ms status = pi.bb_serial_read_open(self._pin_rxd, self._baudrate, self._bytesize) # 50 baud pi.bb_serial_invert(self._pin_rxd, self._inv_rxd) # init bit bongo serial write self.last_wid = None # debug cbs = pi.wave_get_max_cbs() micros = pi.wave_get_max_micros() pulses = pi.wave_get_max_pulses() pass
def __init__(self, **params): super().__init__() self.id = '#' self.params = params self._baudrate = params.get('baudrate', 50) self._bytesize = params.get('bytesize', 5) self._stopbits = params.get('stopbits', 1.5) self._stopbits2 = int(self._stopbits * 2 + 0.5) self._pin_txd = params.get('pin_txd', 17) self._pin_rxd = params.get('pin_rxd', 27) self._pin_fsg_ns = params.get('pin_fsg_ns', 6) # connected to rxd self._pin_rel = params.get('pin_rel', 22) self._pin_dir = params.get('pin_dir', 11) #self._pin_oin = params.get('pin_oin', 10) self._pin_opt = params.get('pin_opt', 9) self._pin_sta = params.get('pin_sta', 23) self._pin_fsg_at = params.get('pin_fsg_at', 8) # button AT optional self._pin_fsg_st = params.get('pin_fsg_st', 7) # button ST optional self._pin_fsg_lt = params.get('pin_fsg_lt', 0) # button LT optional self._pin_status_r = params.get('pin_status_r', 23) # LED red self._pin_status_g = params.get('pin_status_g', 24) # LED green self._inv_rxd = params.get('inv_rxd', False) #self._inv_txd = params.get('inv_txd', False) self._coding = params.get('coding', False) self._loopback = params.get('loopback', True) self._tx_buffer = [] self._rx_buffer = [] self._cb = None self._is_pulse_dial = False self._pulse_dial_count = 0 self._rxd_stable = False # rxd=Low self._rxd_counter = 0 self._time_squelch = 0 self._is_online = False self._is_enabled = False self._is_pulse_dial = False self._use_pulse_dial = True self._use_squelch = True self._use_rxd_observation = True self._status_out = 0 self._status_act = 0 self._status_dst = 0 # init codec character_duration = (self._bytesize + 1.0 + self._stopbits) / self._baudrate self._mc = txCode.BaudotMurrayCode( self._loopback, coding=self._coding, character_duration=character_duration) # init GPIOs pi.set_pad_strength(0, 8) pi.set_mode(self._pin_rxd, pigpio.INPUT) pi.set_pull_up_down(self._pin_rxd, pigpio.PUD_UP) pi.set_glitch_filter(self._pin_rxd, 1000) # 1ms if self._pin_fsg_ns and self._pin_fsg_ns != self._pin_rxd: pi.set_mode(self._pin_fsg_ns, pigpio.INPUT) pi.set_pull_up_down(self._pin_fsg_ns, pigpio.PUD_UP) pi.set_glitch_filter(self._pin_fsg_ns, 1000) # 1ms pi.set_mode(self._pin_txd, pigpio.OUTPUT) #pi.write(self._pin_txd, not self._inv_txd) pi.write(self._pin_txd, 1) pi.set_mode(self._pin_opt, pigpio.OUTPUT) pi.write(self._pin_opt, 0) pi.set_mode(self._pin_rel, pigpio.OUTPUT) # relay for commutating pi.write(self._pin_rel, 0) # pos polarity pi.set_mode(self._pin_dir, pigpio.OUTPUT) # direction of comminication pi.write(self._pin_dir, 0) # 1=transmitting if self._pin_status_r and self._pin_status_g: self._status_LED_r = LED_PWM(self._pin_status_r) self._status_LED_g = LED_PWM(self._pin_status_g) self.status('INIT') if self._pin_fsg_at: self._button_at = Button(self._pin_fsg_at, self._callback_button_at) if self._pin_fsg_st: self._button_st = Button(self._pin_fsg_st, self._callback_button_st) if self._pin_fsg_lt: self._button_lt = Button(self._pin_fsg_lt, self._callback_button_lt) self._set_enable(False) self._set_online(False) # init bit bongo serial read try: status = pi.bb_serial_read_close( self._pin_rxd ) # try to close if it is still open from last debug except: pass status = pi.bb_serial_read_open(self._pin_rxd, self._baudrate, self._bytesize) pi.bb_serial_invert(self._pin_rxd, self._inv_rxd) # init bit bongo serial write self.last_wid = None