I'm struggling to gracefully close a script when the clients send the "stop" command.
As the script is wrote, it actually exit with the following error:
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(*self._args, **self._kwargs)
File "server.py", line 248, in start_server
conn, addr = soc.accept()
File "/usr/lib/python3.5/socket.py", line 195, in accept
fd, addr = self._accept()
OSError: [Errno 22] Invalid argument
Any suggestion?
#!/usr/bin/python3
#################################################################################
# BLE PRESENCE FOR DOMOTICZ #
# #
# AUTHOR: MARCO BAGLIVO (ITALY) (https://github.com/mydomo) #
# #
#################################################################################
# BLE_SCAN LIBRARY IS A FORK OF https://github.com/flyinactor91/RasPi-iBeacons #
#################################################################################
#################################################################################
# INSTALL REQUIREMENTS ON UBUNTU SERVER 16.04: #
# #
# sudo apt-get install -y libbluetooth-dev bluez #
# sudo apt-get install python-dev python3-dev python3-setuptools python3-pip #
# sudo pip3 install pybluez #
# #
#################################################################################
import socket
from lib import ble_scan
from threading import Thread
import sys
import os
import time
import bluetooth._bluetooth as bluez
import signal
import subprocess
from collections import OrderedDict
##########- CONFIGURE SCRIPT -##########
socket_ip = '0.0.0.0'
socket_port = 12345
min_inval_between_batt_level_readings = 3600
##########- CONFIGURE TRANSLATIONS -##########
lang_SCAN_STOPPED = 'Scanning stopped by other function'
lang_READING_LOCK = 'Reading in progress...'
lang_READING_START = 'Reading started'
##########- START VARIABLE INITIALIZATION -##########
mode = ''
beacons_detected = ''
batt_lev_detected = ''
scan_beacon_data = True
ble_value = ''
devices_to_analize = {}
batt_lev_detected = {}
read_value_lock = False
##########- END VARIABLE INITIALIZATION -##########
##########- START FUNCTION THAT HANDLE CLIENT INPUT -##########
def socket_input_process(input_string):
global mode
global devices_to_analize
global lang_SCAN_STOPPED
global lang_READING_LOCK
global lang_READING_START
###- TRANSMIT BEACON DATA -###
# check if client requested "beacon_data"
if input_string == 'beacon_data':
# if beacon scanning function has being stopped in order to process one other request (ex.: battery level) warn the client
if scan_beacon_data == False:
return str(lang_SCAN_STOPPED)
# if beacon scanning function is active send the data to the client
if scan_beacon_data == True:
# set operative mode to beacon_data
mode = 'beacon_data'
# return beacons_detected ordered by timestamp ASC (tnx to: JkShaw - http://stackoverflow.com/questions/43715921/python3-ordering-a-complex-dict)
# return "just" the last 300 results to prevent the end of the socket buffer (each beacon data is about 45 bytes)
return str(sorted(beacons_detected.items(), key=lambda x: x[1][1], reverse=True)[:300])
###- TRANSMIT BATTERY LEVEL -###
# check if the request start with battery_level:
if input_string.startswith('battery_level:'):
# trim "battery_level:" from the request
string_devices_to_analize = input_string.replace("battery_level: ", "")
# split each MAC address in a list in order to be processed
devices_to_analize = string_devices_to_analize.split(',')
# set operative mode to battery_level
mode = 'battery_level'
# if the reading has already requested and there is no result ask to wait
if not batt_lev_detected and read_value_lock == True:
return str(lang_READING_LOCK)
# if the reading is requested for the first time start say that will start
elif not batt_lev_detected and read_value_lock == False:
return str(lang_READING_START)
# if is present a battery data send it
else:
return str(batt_lev_detected)
###- STOP RUNNING SERVICES -###
if input_string == 'stop':
killer.kill_now = True
print ('service stopping')
return str('Service stopping')
##########- END FUNCTION THAT HANDLE CLIENT INPUT -##########
##########- START FUNCTION THAT HANDLE SOCKET'S TRANSMISSION -##########
def client_thread(conn, ip, port, MAX_BUFFER_SIZE = 32768):
# the input is in bytes, so decode it
input_from_client_bytes = conn.recv(MAX_BUFFER_SIZE)
# MAX_BUFFER_SIZE is how big the message can be
# this is test if it's too big
siz = sys.getsizeof(input_from_client_bytes)
if siz >= MAX_BUFFER_SIZE:
print("The length of input is probably too long: {}".format(siz))
# decode input and strip the end of line
input_from_client = input_from_client_bytes.decode("utf8").rstrip()
res = socket_input_process(input_from_client)
#print("Result of processing {} is: {}".format(input_from_client, res))
vysl = res.encode("utf8") # encode the result string
conn.sendall(vysl) # send it to client
conn.close() # close connection
##########- END FUNCTION THAT HANDLE SOCKET'S TRANSMISSION -##########
def usb_dongle_reset():
process0 = subprocess.Popen("sudo hciconfig hci0 down", stdout=subprocess.PIPE, shell=True)
process0.communicate()
process1 = subprocess.Popen("sudo hciconfig hci0 reset", stdout=subprocess.PIPE, shell=True)
process1.communicate()
process2 = subprocess.Popen("sudo /etc/init.d/bluetooth restart", stdout=subprocess.PIPE, shell=True)
process2.communicate()
process3 = subprocess.Popen("sudo hciconfig hci0 up", stdout=subprocess.PIPE, shell=True)
process3.communicate()
def ble_scanner():
global beacons_detected
dev_id = 0
usb_dongle_reset()
try:
sock = bluez.hci_open_dev(dev_id)
#print ("ble thread started")
except:
print ("error accessing bluetooth device... restart in progress!")
usb_dongle_reset()
ble_scan.hci_le_set_scan_parameters(sock)
ble_scan.hci_enable_le_scan(sock)
beacons_detected = {}
while (scan_beacon_data == True) and (not killer.kill_now):
try:
returnedList = ble_scan.parse_events(sock, 25)
for beacon in returnedList:
MAC, RSSI, LASTSEEN = beacon.split(',')
beacons_detected[MAC] = [RSSI,LASTSEEN]
time.sleep(1)
except:
print ("failed restarting device... let's try again!")
usb_dongle_reset()
dev_id = 0
sock = bluez.hci_open_dev(dev_id)
ble_scan.hci_le_set_scan_parameters(sock)
ble_scan.hci_enable_le_scan(sock)
time.sleep(1)
def read_battery_level():
global scan_beacon_data
global mode
global batt_lev_detected
global read_value_lock
global min_inval_between_batt_level_readings
uuid_to_check = '0x2a19'
time_difference = 0
while (not killer.kill_now):
if mode == 'battery_level' and read_value_lock == False:
read_value_lock = True
#print ("Dispositivi da analizzare: " + str(devices_to_analize))
for device in devices_to_analize:
device_to_connect = device
#print ("Analizzo dispositivo: " + str(device))
# i'm reading the value stored
battery_level_moderator = str(batt_lev_detected.get(device, "Never"))
# cleaning the value stored
cleaned_battery_level_moderator = str(battery_level_moderator.replace("[", "").replace("]", "").replace(" ", "").replace("'", ""))
# assign the battery level and the timestamp to different variables
if cleaned_battery_level_moderator != "Never":
stored_batterylevel, stored_timestamp = cleaned_battery_level_moderator.split(',')
time_difference = int(time.time()) - int(stored_timestamp)
if (int(min_inval_between_batt_level_readings) <= int(time_difference)) or (str(cleaned_battery_level_moderator) == "Never") or (str(stored_batterylevel) == '255'):
scan_beacon_data = False
usb_dongle_reset()
#PUT HERE THE CODE TO READ THE BATTERY LEVEL
try:
handle_ble = os.popen("sudo hcitool lecc --random " + device_to_connect + " | awk '{print $3}'").read()
handle_ble_connect = os.popen("sudo hcitool ledc " + handle_ble).read()
#ble_value = int(os.popen("sudo gatttool -t random --char-read --uuid " + uuid_to_check + " -b " + device_to_connect + " | awk '{print $4}'").read() ,16)
ble_value = os.popen("sudo gatttool -t random --char-read --uuid " + uuid_to_check + " -b " + device_to_connect + " | awk '{print $4}'").read()
except:
ble_value = 'nd'
if ble_value != '':
ble_value = int(ble_value ,16)
if ble_value == '':
ble_value = '255'
time_checked = str(int(time.time()))
batt_lev_detected[device] = [ble_value,time_checked]
read_value_lock = False
#print (batt_lev_detected)
#AS SOON AS IT FINISH RESTART THE scan_beacon_data PROCESS
scan_beacon_data = True
mode = 'beacon_data'
Thread(target=ble_scanner).start()
time.sleep(1)
def start_server():
global soc
soc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# this is for easy starting/killing the app
soc.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#print('Socket created')
try:
soc.bind((socket_ip, socket_port))
# print('Socket bind complete')
except socket.error as msg:
# print('Bind failed. Error : ' + str(sys.exc_info()))
sys.exit()
#Start listening on socket
soc.listen(10)
#print('Socket now listening')
# for handling task in separate jobs we need threading
#from threading import Thread
# this will make an infinite loop needed for
# not reseting server for every client
while (not killer.kill_now):
conn, addr = soc.accept()
ip, port = str(addr[0]), str(addr[1])
#print('Accepting connection from ' + ip + ':' + port)
try:
Thread(target=client_thread, args=(conn, ip, port)).start()
except:
print("Terible error!")
import traceback
traceback.print_exc()
soc.close()
def kill_socket():
global soc
global kill_now
kill_socket_switch = False
while (not kill_socket_switch):
if killer.kill_now:
print ("KILL_SOCKET PROVA A CHIUDERE IL SOCKET")
time.sleep(1)
soc.shutdown(socket.SHUT_RDWR)
soc.close()
kill_socket_switch = True
time.sleep(1)
### MAIN PROGRAM ###
class GracefulKiller:
kill_now = False
def __init__(self):
signal.signal(signal.SIGINT, self.exit_gracefully)
signal.signal(signal.SIGTERM, self.exit_gracefully)
def exit_gracefully(self,signum, frame):
global soc
self.kill_now = True
print ('Program stopping...')
if __name__ == '__main__':
killer = GracefulKiller()
Thread(target=start_server).start()
Thread(target=ble_scanner).start()
Thread(target=read_battery_level).start()
Thread(target=kill_socket).start()
# print ("End of the program. I was killed gracefully :)")
Related
My issue is that I have a ports.txt file in it has 4 port numbers. I wish for this program to scan all port numbers specified within the txt file. currently It will only scan the first port number listed in the txt file against the 40 odd IP addresses. I hope my formatting is correct and my detail is enough. ty
import socket
import os
import sys
from datetime import datetime
import win32evtlogutil
import win32evtlog
def main():
### call step 1 function
ipList = network_addr()
# call step 2 function
portList = read_ports()
print(portList)
#call step 3 function
for ip in ipList:
for port in portList:
scan_ports(ip,port)
# call step 4 function
report_to_EventViewer(ipList[0:10], 2) # warning
#report_to_EventViewer(ipList, 1) # error
# processing inputs
# Step 1: process input 1 (subnet or network address):
def network_addr():
while True:
ip_list = []
subnet_Addr = input('Enter a Class-C Network Address or subnet with format (x.x.x): ')
subnet = subnet_Addr.split('.') # subnet is a list of 3 items (octets)
try:
if (len(subnet)==3 and 192<=int(subnet[0])<=223 and 0<=int(subnet[1])<=255 and 0<=int(subnet[2])<=255):
#return subnet_Addr
print('valid subnet: ',subnet_Addr)
for ip in range(11,40,2):
ip_temp = subnet_Addr + '.' + str(ip)
ip_list.append(ip_temp)
return ip_list
else:
value = 'wrong subnet entered'
print(value)
except ValueError:
print('wrong subnet entered, octects must be digits')
# Step 2: process input 2 (read port numbers from ports.txt):
def read_ports():
with open("ports.txt", 'r') as file_path:
port_list = []
for port in file_path:
try:
if int(port) in port_list:
print(f'port: {port} already exists')
else:
port_list.append(int(port))
except:
print(f'the port number: {port} is not a valid integer')
return port_list
else:
print('ports.txt is empty \n .... Exiting Port Scan App')
sys.exit()
# Step 3: scan ports
def scan_ports(ip,port):
# to get and format system time
dateTimeObj = datetime.now()
timeStamp = dateTimeObj.strftime("%d-%b-%Y (%H:%M:%S)")
try:
# open log file
with open("ip_port_log.txt","+r") as log:
# create client socket
socket.setdefaulttimeout(0.1)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip,port))
if result == 0:
data = "IP:" + ip + ":" + str(port) + " Open " + timeStamp
# write_to_console or display on screen
print(data)
# write in log file
log.write(data + "\n")
else:
data = "IP:" + ip + ":" + str(port) + " Closed/Filtered or host is offline " + timeStamp
# write_to_console or display on screen
print(data)
# write in log file
log.write(data + "\n")
# close the client socket
sock.close()
except socket.error:
print("Can't connect to IP: ", ip)
sys.exit()
except KeyboardInterrupt:
print("User pressed Ctrl+c")
sys.exit()
# Step 4: Report to Event Viewer
# output 3
def report_to_EventViewer(mylist, eventtype):
IP_EVT_APP_NAME = " CheckIPPort - IP-Port Scan Application"
IP_EVT_ID = 7040 ##According to ???
IP_EVT_CATEG = 9876 ##According to ???
IP_EVT_TYPE = win32evtlog.EVENTLOG_WARNING_TYPE # WARNING=2
IP_EVT_ERR = win32evtlog.EVENTLOG_ERROR_TYPE # ERROR=1
IP_EVT_STRS = mylist
IP_EVT_DATA = b"Scan IP Address Event Data"
win32evtlogutil.ReportEvent(IP_EVT_APP_NAME, \
IP_EVT_ID, \
eventCategory=IP_EVT_CATEG, \
eventType=eventtype, \
strings=IP_EVT_STRS, \
data=IP_EVT_DATA)
main()
you issue is in your read_ports method, you return inside the loop so it will ALWAYS only read the first one. Rewrite the method to something like:
def read_ports():
with open("ports.txt", 'r') as file_path:
port_list = []
for port in file_path:
try:
if int(port) in port_list:
print(f'port: {port} already exists')
else:
port_list.append(int(port))
except:
print(f'the port number: {port} is not a valid integer')
if not len(port_list):
print('ports.txt is empty \n .... Exiting Port Scan App')
sys.exit()
return port_list
I have a USRobotics 56K Modem with USB connected to a linux system. I downloaded the sample python codes that can play and record audio through the modem on the following website USRobotics Sample Code. I have tested them and the codes work flawlessly. However, for some reason I can't seem to find an answer to my question on the internet. So, I am asking here. Is it possible to record audio while playing different audio wave file at the same time on USRobotics modem using the following python codes?
Playing Audio File:
import serial
import time
import threading
import atexit
import sys
import re
import wave
analog_modem = serial.Serial()
analog_modem.port = "/dev/ttyACM0"
analog_modem.baudrate = 57600 #9600
analog_modem.bytesize = serial.EIGHTBITS #number of bits per bytes
analog_modem.parity = serial.PARITY_NONE #set parity check: no parity
analog_modem.stopbits = serial.STOPBITS_ONE #number of stop bits
analog_modem.timeout = 3 #non-block read
analog_modem.xonxoff = False #disable software flow control
analog_modem.rtscts = False #disable hardware (RTS/CTS) flow control
analog_modem.dsrdtr = False #disable hardware (DSR/DTR) flow control
analog_modem.writeTimeout = 3 #timeout for write
# Used in global event listener
disable_modem_event_listener = True
RINGS_BEFORE_AUTO_ANSWER = 2
#=================================================================
# Initialize Modem
#=================================================================
def init_modem_settings():
# Opean Serial Port
try:
analog_modem.open()
except:
print "Error: Unable to open the Serial Port."
sys.exit()
# Initialize
try:
analog_modem.flushInput()
analog_modem.flushOutput()
# Test Modem connection, using basic AT command.
if not exec_AT_cmd("AT"):
print "Error: Unable to access the Modem"
# reset to factory default.
if not exec_AT_cmd("ATZ3"):
print "Error: Unable reset to factory default"
# Display result codes in verbose form
if not exec_AT_cmd("ATV1"):
print "Error: Unable set response in verbose form"
# Enable Command Echo Mode.
if not exec_AT_cmd("ATE1"):
print "Error: Failed to enable Command Echo Mode"
# Enable formatted caller report.
if not exec_AT_cmd("AT+VCID=1"):
print "Error: Failed to enable formatted caller report."
# Enable formatted caller report.
#if not exec_AT_cmd("AT+FCLASS=8"):
# print "Error: Failed to enable formatted caller report."
analog_modem.flushInput()
analog_modem.flushOutput()
except:
print "Error: unable to Initialize the Modem"
sys.exit()
#=================================================================
#=================================================================
# Execute AT Commands on the Modem
#=================================================================
def exec_AT_cmd(modem_AT_cmd):
try:
global disable_modem_event_listener
disable_modem_event_listener = True
cmd = modem_AT_cmd + "\r"
analog_modem.write(cmd.encode())
modem_response = analog_modem.readline()
modem_response = modem_response + analog_modem.readline()
print modem_response
disable_modem_event_listener = False
if ((modem_AT_cmd == "AT+VTX") or (modem_AT_cmd == "AT+VRX")) and ("CONNECT" in modem_response):
# modem in TAD mode
return True
elif "OK" in modem_response:
# Successful command execution
return True
else:
# Failed command execution
return False
except:
disable_modem_event_listener = False
print "Error: unable to write AT command to the modem..."
return()
#=================================================================
#=================================================================
# Recover Serial Port
#=================================================================
def recover_from_error():
try:
exec_AT_cmd("ATH")
except:
pass
analog_modem.close()
init_modem_settings()
try:
analog_modem.close()
except:
pass
try:
init_modem_settings()
except:
pass
try:
exec_AT_cmd("ATH")
except:
pass
#=================================================================
#=================================================================
# Play wav file
#=================================================================
def play_audio():
print "Play Audio Msg - Start"
# Enter Voice Mode
if not exec_AT_cmd("AT+FCLASS=8"):
print "Error: Failed to put modem into voice mode."
return
# Compression Method and Sampling Rate Specifications
# Compression Method: 8-bit linear / Sampling Rate: 8000MHz
if not exec_AT_cmd("AT+VSM=128,8000"):
print "Error: Failed to set compression method and sampling rate specifications."
return
# Put modem into TAD Mode
if not exec_AT_cmd("AT+VLS=1"):
print "Error: Unable put modem into TAD mode."
return
# Put modem into TAD Mode
if not exec_AT_cmd("AT+VTX"):
print "Error: Unable put modem into TAD mode."
return
time.sleep(1)
# Play Audio File
global disable_modem_event_listener
disable_modem_event_listener = True
wf = wave.open('sample.wav','rb')
chunk = 1024
data = wf.readframes(chunk)
while data != '':
analog_modem.write(data)
data = wf.readframes(chunk)
# You may need to change this sleep interval to smooth-out the audio
time.sleep(.12)
wf.close()
#analog_modem.flushInput()
#analog_modem.flushOutput()
cmd = "<DLE><ETX>" + "\r"
analog_modem.write(cmd.encode())
# 2 Min Time Out
timeout = time.time() + 60*2
while 1:
modem_data = analog_modem.readline()
if "OK" in modem_data:
break
if time.time() > timeout:
break
disable_modem_event_listener = False
cmd = "ATH" + "\r"
analog_modem.write(cmd.encode())
print "Play Audio Msg - END"
return
#=================================================================
#=================================================================
# Modem Data Listener
#=================================================================
def read_data():
global disable_modem_event_listener
ring_data = ""
while 1:
if not disable_modem_event_listener:
modem_data = analog_modem.readline()
if modem_data != "":
print modem_data
if "b" in modem_data.strip(chr(16)):
print "b in modem data"
print "b count:"
print ((modem_data.strip(chr(16))).count("b"))
print "total length:"
print len(modem_data.strip(chr(16)))
print modem_data
if ((modem_data.strip(chr(16))).count("b")) == len(modem_data.strip(chr(16))):
print "all Bs in mode data"
#Terminate the call
if not exec_AT_cmd("ATH"):
print "Error: Busy Tone - Failed to terminate the call"
print "Trying to revoer the serial port"
recover_from_error()
else:
print "Busy Tone: Call Terminated"
if "s" == modem_data.strip(chr(16)):
#Terminate the call
if not exec_AT_cmd("ATH"):
print "Error: Silence - Failed to terminate the call"
print "Trying to revoer the serial port"
recover_from_error()
else:
print "Silence: Call Terminated"
if ("RING" in modem_data) or ("DATE" in modem_data) or ("TIME" in modem_data) or ("NMBR" in modem_data):
if "RING" in modem_data.strip(chr(16)):
ring_data = ring_data + modem_data
ring_count = ring_data.count("RING")
if ring_count == 1:
pass
print modem_data
elif ring_count == RINGS_BEFORE_AUTO_ANSWER:
ring_data = ""
play_audio()
#=================================================================
#=================================================================
# Close the Serial Port
#=================================================================
def close_modem_port():
try:
exec_AT_cmd("ATH")
except:
pass
try:
if analog_modem.isOpen():
analog_modem.close()
print ("Serial Port closed...")
except:
print "Error: Unable to close the Serial Port."
sys.exit()
#=================================================================
init_modem_settings()
#Start a new thread to listen to modem data
data_listener_thread = threading.Thread(target=read_data)
data_listener_thread.start()
# Close the Modem Port when the program terminates
atexit.register(close_modem_port)
Recording Audio:
import serial
import time
import threading
import atexit
import sys
import re
import wave
from datetime import datetime
import os
import fcntl
import subprocess
RINGS_BEFORE_AUTO_ANSWER = 2 #Must be greater than 1
MODEM_RESPONSE_READ_TIMEOUT = 120 #Time in Seconds (Default 120 Seconds)
MODEM_NAME = 'U.S. Robotics' # Modem Manufacturer, For Ex: 'U.S. Robotics' if the 'lsusb' cmd output is similar to "Bus 001 Device 004: ID 0baf:0303 U.S. Robotics"
# Record Voice Mail Variables
REC_VM_MAX_DURATION = 120 # Time in Seconds
# Used in global event listener
disable_modem_event_listener = True
# Global Modem Object
analog_modem = serial.Serial()
audio_file_name = ''
#=================================================================
# Set COM Port settings
#=================================================================
def set_COM_port_settings(com_port):
analog_modem.port = com_port
analog_modem.baudrate = 57600 #9600 #115200
analog_modem.bytesize = serial.EIGHTBITS #number of bits per bytes
analog_modem.parity = serial.PARITY_NONE #set parity check: no parity
analog_modem.stopbits = serial.STOPBITS_ONE #number of stop bits
analog_modem.timeout = 3 #non-block read
analog_modem.xonxoff = False #disable software flow control
analog_modem.rtscts = False #disable hardware (RTS/CTS) flow control
analog_modem.dsrdtr = False #disable hardware (DSR/DTR) flow control
analog_modem.writeTimeout = 3 #timeout for write
#=================================================================
#=================================================================
# Initialize Modem
#=================================================================
def detect_COM_port():
# List all the Serial COM Ports on Raspberry Pi
proc = subprocess.Popen(['ls /dev/tty[A-Za-z]*'], shell=True, stdout=subprocess.PIPE)
com_ports = proc.communicate()[0]
com_ports_list = com_ports.split('\n')
# Find the right port associated with the Voice Modem
for com_port in com_ports_list:
if 'tty' in com_port:
#Try to open the COM Port and execute AT Command
try:
# Set the COM Port Settings
set_COM_port_settings(com_port)
analog_modem.open()
except:
print "Unable to open COM Port: " + com_port
pass
else:
#Try to put Modem in Voice Mode
if not exec_AT_cmd("AT+FCLASS=8", "OK"):
print "Error: Failed to put modem into voice mode."
if analog_modem.isOpen():
analog_modem.close()
else:
# Found the COM Port exit the loop
print "Modem COM Port is: " + com_port
analog_modem.flushInput()
analog_modem.flushOutput()
break
#=================================================================
#=================================================================
# Initialize Modem
#=================================================================
def init_modem_settings():
# Detect and Open the Modem Serial COM Port
try:
detect_COM_port()
except:
print "Error: Unable to open the Serial Port."
sys.exit()
# Initialize the Modem
try:
# Flush any existing input outout data from the buffers
analog_modem.flushInput()
analog_modem.flushOutput()
# Test Modem connection, using basic AT command.
if not exec_AT_cmd("AT"):
print "Error: Unable to access the Modem"
# reset to factory default.
if not exec_AT_cmd("ATZ3"):
print "Error: Unable reset to factory default"
# Display result codes in verbose form
if not exec_AT_cmd("ATV1"):
print "Error: Unable set response in verbose form"
# Enable Command Echo Mode.
if not exec_AT_cmd("ATE1"):
print "Error: Failed to enable Command Echo Mode"
# Enable formatted caller report.
if not exec_AT_cmd("AT+VCID=1"):
print "Error: Failed to enable formatted caller report."
# Flush any existing input outout data from the buffers
analog_modem.flushInput()
analog_modem.flushOutput()
except:
print "Error: unable to Initialize the Modem"
sys.exit()
#=================================================================
#=================================================================
# Reset Modem
#=================================================================
def reset_USB_Device():
# Close the COM Port if it's open
try:
if analog_modem.isOpen():
analog_modem.close()
except:
pass
# Equivalent of the _IO('U', 20) constant in the linux kernel.
USBDEVFS_RESET = ord('U') << (4*2) | 20
dev_path = ""
# Bases on 'lsusb' command, get the usb device path in the following format -
# /dev/bus/usb/<busnum>/<devnum>
proc = subprocess.Popen(['lsusb'], stdout=subprocess.PIPE)
out = proc.communicate()[0]
lines = out.split('\n')
for line in lines:
if MODEM_NAME in line:
parts = line.split()
bus = parts[1]
dev = parts[3][:3]
dev_path = '/dev/bus/usb/%s/%s' % (bus, dev)
# Reset the USB Device
fd = os.open(dev_path, os.O_WRONLY)
try:
fcntl.ioctl(fd, USBDEVFS_RESET, 0)
print "Modem reset successful"
finally:
os.close(fd)
# Re-initialize the Modem
init_modem_settings()
#=================================================================
#=================================================================
# Execute AT Commands at the Modem
#=================================================================
def exec_AT_cmd(modem_AT_cmd, expected_response="OK"):
global disable_modem_event_listener
disable_modem_event_listener = True
try:
# Send command to the Modem
analog_modem.write((modem_AT_cmd + "\r").encode())
# Read Modem response
execution_status = read_AT_cmd_response(expected_response)
disable_modem_event_listener = False
# Return command execution status
return execution_status
except:
disable_modem_event_listener = False
print "Error: Failed to execute the command"
return False
#=================================================================
#=================================================================
# Read AT Command Response from the Modem
#=================================================================
def read_AT_cmd_response(expected_response="OK"):
# Set the auto timeout interval
start_time = datetime.now()
try:
while 1:
# Read Modem Data on Serial Rx Pin
modem_response = analog_modem.readline()
print modem_response
# Recieved expected Response
if expected_response == modem_response.strip(' \t\n\r' + chr(16)):
return True
# Failed to execute the command successfully
elif "ERROR" in modem_response.strip(' \t\n\r' + chr(16)):
return False
# Timeout
elif (datetime.now()-start_time).seconds > MODEM_RESPONSE_READ_TIMEOUT:
return False
except:
print "Error in read_modem_response function..."
return False
#=================================================================
#=================================================================
# Recover Serial Port
#=================================================================
def recover_from_error():
# Stop Global Modem Event listener
global disable_modem_event_listener
disable_modem_event_listener = True
# Reset USB Device
reset_USB_Device()
# Start Global Modem Event listener
disable_modem_event_listener = False
#=================================================================
#=================================================================
# Read DTMF Digits
#=================================================================
def dtmf_digits(modem_data):
digits = ""
digit_list = re.findall('/(.+?)~', modem_data)
for d in digit_list:
digits= digits + d[0]
return digits
#=================================================================
#=================================================================
# Record wav file (Voice Msg/Mail)
#=================================================================
def record_audio():
print "Record Audio Msg - Start"
# Enter Voice Mode
if not exec_AT_cmd("AT+FCLASS=8","OK"):
print "Error: Failed to put modem into voice mode."
return
# Set speaker volume to normal
if not exec_AT_cmd("AT+VGT=128","OK"):
print "Error: Failed to set speaker volume to normal."
return
# Compression Method and Sampling Rate Specifications
# Compression Method: 8-bit linear / Sampling Rate: 8000MHz
if not exec_AT_cmd("AT+VSM=128,8000","OK"):
print "Error: Failed to set compression method and sampling rate specifications."
return
# Disables silence detection (Value: 0)
if not exec_AT_cmd("AT+VSD=128,0","OK"):
print "Error: Failed to disable silence detection."
return
# Put modem into TAD Mode
if not exec_AT_cmd("AT+VLS=1","OK"):
print "Error: Unable put modem into TAD mode."
return
# Enable silence detection.
# Select normal silence detection sensitivity
# and a silence detection interval of 5 s.
if not exec_AT_cmd("AT+VSD=128,50","OK"):
print "Error: Failed tp enable silence detection."
return
# Play beep.
if not exec_AT_cmd("AT+VTS=[933,900,100]","OK"):
print "Error: Failed to play 1.2 second beep."
#return
# Select voice receive mode
if not exec_AT_cmd("AT+VRX","CONNECT"):
print "Error: Unable put modem into voice receive mode."
return
# Record Audio File
global disable_modem_event_listener
disable_modem_event_listener = True
# Set the auto timeout interval
start_time = datetime.now()
CHUNK = 1024
audio_frames = []
while 1:
# Read audio data from the Modem
audio_data = analog_modem.read(CHUNK)
# Check if <DLE>b is in the stream
if ((chr(16)+chr(98)) in audio_data):
print "Busy Tone... Call will be disconnected."
break
# Check if <DLE>s is in the stream
if ((chr(16)+chr(115)) in audio_data):
print "Silence Detected... Call will be disconnected."
break
# Check if <DLE><ETX> is in the stream
if (("<DLE><ETX>").encode() in audio_data):
print "<DLE><ETX> Char Recieved... Call will be disconnected."
break
# Timeout
elif ((datetime.now()-start_time).seconds) > REC_VM_MAX_DURATION:
print "Timeout - Max recording limit reached."
break
# Add Audio Data to Audio Buffer
audio_frames.append(audio_data)
global audio_file_name
# Save the Audio into a .wav file
wf = wave.open(audio_file_name, 'wb')
wf.setnchannels(1)
wf.setsampwidth(1)
wf.setframerate(8000)
wf.writeframes(b''.join(audio_frames))
wf.close()
# Reset Audio File Name
audio_file_name = ''
# Send End of Voice Recieve state by passing "<DLE>!"
if not exec_AT_cmd((chr(16)+chr(33)),"OK"):
print "Error: Unable to signal end of voice receive state"
# Hangup the Call
if not exec_AT_cmd("ATH","OK"):
print "Error: Unable to hang-up the call"
# Enable global event listener
disable_modem_event_listener = False
print "Record Audio Msg - END"
return
#=================================================================
#=================================================================
# Data Listener
#=================================================================
def read_data():
global disable_modem_event_listener
ring_data = ""
while 1:
if not disable_modem_event_listener:
modem_data = analog_modem.readline()
if modem_data != "":
print modem_data
# Check if <DLE>b is in the stream
if (chr(16)+chr(98)) in modem_data:
#Terminate the call
if not exec_AT_cmd("ATH"):
print "Error: Busy Tone - Failed to terminate the call"
print "Trying to revoer the serial port"
recover_from_error()
else:
print "Busy Tone: Call Terminated"
# Check if <DLE>s is in the stream
if (chr(16)+chr(115)) == modem_data:
#Terminate the call
if not exec_AT_cmd("ATH"):
print "Error: Silence - Failed to terminate the call"
print "Trying to revoer the serial port"
recover_from_error()
else:
print "Silence: Call Terminated"
if ("-s".encode() in modem_data) or (("<DLE>-s").encode() in modem_data):
print "silence found during recording"
analog_modem.write(("<DLE>-!" + "\r").encode())
if ("RING" in modem_data) or ("DATE" in modem_data) or ("TIME" in modem_data) or ("NMBR" in modem_data):
global audio_file_name
if ("NMBR" in modem_data):
from_phone = (modem_data[5:]).strip()
if ("DATE" in modem_data):
call_date = (modem_data[5:]).strip()
if ("TIME" in modem_data):
call_time = (modem_data[5:]).strip()
if "RING" in modem_data.strip(chr(16)):
ring_data = ring_data + modem_data
ring_count = ring_data.count("RING")
if ring_count == 1:
pass
elif ring_count == RINGS_BEFORE_AUTO_ANSWER:
ring_data = ""
audio_file_name = from_phone + "_" + call_date + "_" + call_time + "_" + str(datetime.strftime(datetime.now(),"%S")) + ".wav"
from_phone = ''
call_date = ''
call_time = ''
record_audio()
#=================================================================
#=================================================================
# Close the Serial Port
#=================================================================
def close_modem_port():
# Try to close any active call
try:
exec_AT_cmd("ATH")
except:
pass
# Close the Serial COM Port
try:
if analog_modem.isOpen():
analog_modem.close()
print ("Serial Port closed...")
except:
print "Error: Unable to close the Serial Port."
sys.exit()
#=================================================================
# Main Function
init_modem_settings()
# Close the Modem Port when the program terminates
atexit.register(close_modem_port)
# Monitor Modem Serial Port
read_data()
If so, could you please show me a working code.
It is possible. Code you shared use modem in only one way; AT+VTX for Transmit, AT+VRX for receive only. Choose one of code you shared to handle modem first, then use AT+VTR command to put modem send/receive mode.
After that, you should handle modem's transmit and receive buffer at the same time in a while loop; analog_modem.read(var) for recording and analog_modem.write(var) for playing. Also you may want to feed modem's transmit buffer with 0x80s at the 8K bytes per second if play file is shorter than your recording, otherwise modem will send to DTE, 'Transmit Buffer Underrun' codes.
Working code shown below. You may find 'AT Command Set for CX93010 chipset' in internet. All 'import' lines may not be necessary.
phone-TX-RX.py
## Python Ver: 3.9
##--- Inspired/Altered from original code belongs to:
##--- Author: Pradeep Singh
##--- Blog: https://iotbytes.wordpress.com/play-audio-file-on-phone-line-with-raspberry-pi/
##--- Date: 24th June 2018
##--- Version: 1.0
##--- Python Ver: 2.7
##--- Description: This python code will pick an incoming call and play an audio msg on the Phone line.
##------------------------------------------
import serial
import time
import threading
import atexit
import sys
import re
import wave
import os
line = serial.Serial()
line.port = "/dev/ttyACM0"
line.baudrate = 115200
line.bytesize = serial.EIGHTBITS #number of bits per bytes
line.parity = serial.PARITY_NONE #set parity check: no parity
line.stopbits = serial.STOPBITS_ONE #number of stop bits
line.timeout = 3 #non-block read
line.xonxoff = False #disable software flow control
line.rtscts = False #disable hardware (RTS/CTS) flow control
line.dsrdtr = False #disable hardware (DSR/DTR) flow control
line.writeTimeout = 3 #timeout for write
# Used in global event listener
ANSWER_AFTER_RINGS = 1
AT_RESPONSE_TIMEOUT = 3
RING_TIMEOUT = 6 # timeout beetween two rings
MAX_REC_DURATION = 9 # max record duration
playRequested = False
playStarted = False
playFile = None
fileLen = 0
chunkCounter = 0
recRequested = False
recStarted = False
recTimeout = 0
recFile = None
audioFrames = []
ringCount = 0
ringTimeout = 0
modemResponse = bytes("", 'ascii')
# ACSII codes
DLE_CODE = chr(16).encode('ascii') # Data Link Escape (DLE) code
ETX_CODE = chr(3).encode('ascii') # End Transmission (ETX) code
CR_CODE = chr(13).encode('ascii') # Carraige return
LF_CODE = chr(10).encode('ascii') # Line feed
CRLF = (chr(13) + chr(10)).encode('ascii')
OK_STR = "OK\r\n".encode('ascii')
CONNECT_STR = "CONNECT\r\n".encode('ascii')
RING_STR = "RING\r\n".encode('ascii')
FACTORY_RESET = "ATZ\r\n".encode('ascii')
RESET_PROFILE = "ATZ0\r\n".encode('ascii')
GET_MODEM_PRODUCT_CODE = "ATI0\r\n".encode('ascii')
GET_MODEM_SETTINGS = "AT&V\r\n".encode('ascii')
ECHO_OFF = "ATE0\r\n".encode('ascii')
ECHO_ON = "ATE1\r\n".encode('ascii')
ENABLE_FORMATTED_CID = "AT+VCID=1\r\n".encode('ascii')
ENABLE_VERBOSE_CODES = "ATV1\r\n".encode('ascii')
DISABLE_SILENCE_DETECTION = "AT+VSD=0,0\r\n".encode('ascii')
ENABLE_SILENCE_DETECTION_5_SECS = "AT+VSD=0,50\r\n".encode('ascii')
ENABLE_SILENCE_DETECTION_10_SECS = "AT+VSD=0,100\r\n".encode('ascii')
ENTER_VOICE_MODE = "AT+FCLASS=8\r\n".encode('ascii')
ENTER_VOICE_RECIEVE_STATE = "AT+VRX\r\n".encode('ascii')
ENTER_VOICE_TRANSMIT_STATE = "AT+VTX\r\n".encode('ascii')
ENTER_VOICE_TRANSMIT_RECIEVE_STATE = "AT+VTR\r\n".encode('ascii') # Start Voice Transmission and Reception (Voice Duplex)
SEND_VOICE_TONE_BEEP = "AT+VTS=[900,900,120]\r\n".encode('ascii') # 1.2 second beep
GET_VOICE_COMPRESSION_SETTING = "AT+VSM?\r\n".encode('ascii')
GET_VOICE_COMPRESSION_OPTIONS = "AT+VSM=?\r\n".encode('ascii')
SET_VOICE_COMPRESSION = "AT+VSM=1,8000,0,0\r\n".encode('ascii') # 1 = 8-bit unsigned pcm, 8.0 kHz
LINE_OFF_HOOK = "AT+VLS=1\r\n".encode('ascii') # DCE off-hook, connected to telco
LINE_ON_HOOK = "AT+VLS=0\r\n".encode('ascii') # DCE on-hook
TERMINATE_CALL = "ATH\r\n".encode('ascii')
# Modem DLE shielded codes - DCE to DTE modem data
DCE_ANSWER_TONE = (chr(16) + chr(97)).encode('ascii') # <DLE>-a
DCE_BUSY_TONE = (chr(16) + chr(98)).encode('ascii') # <DLE>-b
DCE_FAX_CALLING_TONE = (chr(16) + chr(99)).encode('ascii') # <DLE>-c
DCE_DIAL_TONE = (chr(16) + chr(100)).encode('ascii') # <DLE>-d
DCE_DATA_CALLING_TONE = (chr(16) + chr(101)).encode('ascii') # <DLE>-e
DCE_LINE_REVERSAL = (chr(16) + chr(108)).encode('ascii') # <DLE>-l
DCE_PHONE_ON_HOOK = (chr(16) + chr(104)).encode('ascii') # <DLE>-h
DCE_PHONE_OFF_HOOK = (chr(16) + chr(72)).encode('ascii') # <DLE>-H
DCE_PHONE_OFF_HOOK2 = (chr(16) + chr(80)).encode('ascii') # <DLE>-P
DCE_QUIET_DETECTED = (chr(16) + chr(113)).encode('ascii') # <DLE>-q
DCE_RING = (chr(16) + chr(82)).encode('ascii') # <DLE>-R
DCE_SILENCE_DETECTED = (chr(16) + chr(115)).encode('ascii') # <DLE>-s
DCE_TX_BUFFER_UNDERRUN = (chr(16) + chr(117)).encode('ascii') # <DLE>-u
DCE_END_VOICE_DATA_TX = (chr(16) + chr(3)).encode('ascii') # <DLE><ETX>
# System DLE shielded codes (single DLE) - DTE to DCE commands (used by USR 5637 modem)
DTE_RAISE_VOLUME = (chr(16) + chr(117)).encode('ascii') # <DLE>u
DTE_LOWER_VOLUME = (chr(16) + chr(100)).encode('ascii') # <DLE>d
DTE_END_VOICE_DATA_RX = (chr(16) + chr(33)).encode('ascii') # <DLE>!
DTE_END_VOICE_DATA_TX = (chr(16) + chr(3)).encode('ascii') # <DLE><ETX>
DTE_END_VOICE_DATA_TX_RX = (chr(16) + chr(94)).encode('ascii') # <DLE>^
DTE_CLEAR_TRANSMIT_BUFFER = (chr(16) + chr(24)).encode('ascii') # <DLE><CAN>
#=================================================================
# Initialize Modem
#=================================================================
def initialize_modem():
# Opean Serial Port
try:
line.open()
print ("Serial port open")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: Unable to open the Serial Port.")
sys.exit()
# Initialize
try:
line.reset_input_buffer()
line.reset_output_buffer()
# hang-up if opened
send(TERMINATE_CALL, OK_STR)
# reset to factory default.
send(FACTORY_RESET, OK_STR)
# Disable Command Echo Mode.
send(ECHO_OFF, OK_STR)
# Display result codes in verbose form
send(ENABLE_VERBOSE_CODES, OK_STR)
# Enable formatted caller report.
send(ENABLE_FORMATTED_CID, OK_STR)
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: unable to Initialize the Modem")
sys.exit()
#=================================================================
#=================================================================
# Execute AT Commands on the Modem
#=================================================================
def send(cmd, resp):
global modemResponse
result = False
try:
# Send command to the Modem
line.write(cmd)
print ("sent >:", cmd)
modemResponse = bytes("", 'ascii')
if (resp == ""):
return
timeout = time.time() + AT_RESPONSE_TIMEOUT
while (time.time() < timeout):
if (line.in_waiting != 0): # if response
modemResponse += line.read(line.in_waiting)
if (resp in modemResponse):
result = True
break
print ("rcvd <:", modemResponse)
modemResponse = bytes("", 'ascii')
# Failed command execution
if (result == False):
print ("Modem AT Command timeout")
sys.exit()
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: unable to write AT command to the modem: ", cmd)
sys.exit()
#=================================================================
#=================================================================
# Set Modem Voice Mode
#=================================================================
def set_voice_mod():
# Enter Voice Mode
send(ENTER_VOICE_MODE, OK_STR)
# Compression Method and Sampling Rate Specifications
# Compression Method: Unsigned PCM / Sampling Rate: 8000MHz
send(SET_VOICE_COMPRESSION, OK_STR)
# Open phone line
send(LINE_OFF_HOOK, OK_STR)
# Enable silence detection.
# Select normal silence detection sensitivity and a silence detection interval of 5 s.
send(ENABLE_SILENCE_DETECTION_5_SECS, OK_STR)
# Put modem into voice transmit receive mode
send(ENTER_VOICE_TRANSMIT_RECIEVE_STATE, CONNECT_STR)
#=================================================================
# Play wav file
#=================================================================
def handle_play():
global playRequested, playStarted, playFile, fileLen, chunkCounter
CHUNK = 256
if (playRequested):
if (not playStarted):
# Play Audio File
playFile = wave.open('sample.wav','rb')
fileLen = playFile.getnframes() / CHUNK
chunkCounter = 0
playStarted = True
print ("Play Audio Msg - Start")
else:
if (chunkCounter < fileLen):
if (line.out_waiting < CHUNK):
line.write(playFile.readframes(CHUNK))
chunkCounter = chunkCounter + 1
else:
playFile.close()
playStarted = False
print ("Play Audio Msg - End")
#=================================================================
def handle_record():
global recRequested, recStarted, recTimeout, recFile, audioFrames
if (recRequested):
if (not recStarted):
# Play Audio File
recFile = wave.open('record.wav', 'wb')
recFile.setnchannels(1)
recFile.setsampwidth(1)
recFile.setframerate(8000)
recTimeout = time.time() + MAX_REC_DURATION
audioFrames = []
print ("Record Audio Msg - Start")
recStarted = True
else:
if (line.in_waiting > 0):
# Read audio data from the Modem
audio_data = line.read(line.in_waiting)
# Check if <DLE>b is in the stream
if (DCE_BUSY_TONE in audio_data):
print ("Busy Tone... Call will be disconnected.")
# Check if <DLE>s is in the stream
elif (DCE_SILENCE_DETECTED in audio_data):
print ("Silence Detected... Call will be disconnected.")
# Check if <DLE><ETX> is in the stream
elif (DCE_END_VOICE_DATA_TX in audio_data):
print ("<DLE><ETX> Char Recieved... Call will be disconnected.")
else:
# Add Audio Data to Audio Buffer
audioFrames.append(audio_data)
elif (time.time() > recTimeout):
# Save the Audio into a .wav file
recFile.writeframes(b''.join(audioFrames))
recFile.close()
recStarted = False
print ("Record Audio Msg - End")
#=================================================================
#=================================================================
# Modem Data Listener
#=================================================================
def handle_line():
global playRequested, recRequested, playStarted, recStarted, modemResponse, ringCount, ringTimeout
# print ("Waiting for ", str(ANSWER_AFTER_RINGS), " ring(s)")
if (playRequested or recRequested):
if (playRequested and (not playStarted)): # play ended
playRequested = False
if (recRequested and (not recStarted)): # record ended
recRequested = False
if ((not playStarted) and (not recStarted)): # play and record ended, line idle
send(DTE_END_VOICE_DATA_TX_RX, DCE_END_VOICE_DATA_TX)
send(DCE_END_VOICE_DATA_TX, OK_STR)
#Terminate the call
print ("Hang-up: Call ended")
send(TERMINATE_CALL, OK_STR)
return
if (line.in_waiting != 0):
modemResponse += line.read(line.in_waiting)
if (len(modemResponse) != 0):
print ("rcvd <:", modemResponse)
if (DCE_BUSY_TONE in modemResponse): #3 busy tone
#Terminate the call
print ("Busy Tone: Call Terminated")
send(TERMINATE_CALL, OK_STR)
elif (DCE_SILENCE_DETECTED in modemResponse): #3 silence
#Terminate the call
print ("Silence: Call Terminated")
send(TERMINATE_CALL, OK_STR)
elif (RING_STR in modemResponse): # or ("DATE" in modemResponse) or ("TIME" in modemResponse) or ("NMBR" in modemResponse):
modemResponse = bytes("", 'ascii')
ringTimeout = time.time() + RING_TIMEOUT
ringCount = ringCount + 1
if (ringCount == ANSWER_AFTER_RINGS):
print ("Ring: Call Started")
ringTimeout = 0
ringCount = 0
set_voice_mod()
playRequested = True
recRequested = True
if ((ringTimeout != 0) and (time.time() > ringTimeout)): # new ring did not come before play_audio
ringTimeout = 0
ringCount = 0
modemResponse = bytes("", 'ascii')
#=================================================================
#=================================================================
# Close the Serial Port
#=================================================================
def close_modem_port():
send(TERMINATE_CALL, OK_STR)
try:
if line.isOpen():
line.close()
print ("Serial Port closed...")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: Unable to close the Serial Port.")
sys.exit()
#=================================================================
try:
os.remove('record.wav')
except OSError:
pass
initialize_modem()
atexit.register(close_modem_port)
while(True):
handle_line()
handle_play()
handle_record()
And code below with one handler for record and play.
phone-SingleHandler.py
# Python Ver: 3.9
##--- Inspired/Altered from original code belongs to:
##--- Author: Pradeep Singh
##--- Blog: https://iotbytes.wordpress.com/play-audio-file-on-phone-line-with-raspberry-pi/
##--- Date: 24th June 2018
##--- Version: 1.0
##--- Python Ver: 2.7
##--- Description: This python code will pick an incoming call and play an audio msg on the Phone line.
##------------------------------------------
import serial
import time
import threading
import atexit
import sys
import re
import wave
import os
line = serial.Serial()
line.port = "/dev/ttyACM0"
line.baudrate = 115200
line.bytesize = serial.EIGHTBITS #number of bits per bytes
line.parity = serial.PARITY_NONE #set parity check: no parity
line.stopbits = serial.STOPBITS_ONE #number of stop bits
line.timeout = 3 #non-block read
line.xonxoff = False #disable software flow control
line.rtscts = False #disable hardware (RTS/CTS) flow control
line.dsrdtr = False #disable hardware (DSR/DTR) flow control
line.writeTimeout = 3 #timeout for write
# Used in global event listener
ANSWER_AFTER_RINGS = 1
AT_RESPONSE_TIMEOUT = 3
RING_TIMEOUT = 6 # timeout beetween two rings
MAX_REC_DURATION = 9 # max record duration
playStarted = False
playFile = None
fileLen = 0
chunkCounter = 0
recStarted = False
recTimeout = 0
recFile = None
audioFrames = []
lineRXbuffer = []
lineTXbuffer = []
ringCount = 0
ringTimeout = 0
modemResponse = bytes("", 'ascii')
# ACSII codes
DLE_CODE = chr(16).encode('ascii') # Data Link Escape (DLE) code
ETX_CODE = chr(3).encode('ascii') # End Transmission (ETX) code
CR_CODE = chr(13).encode('ascii') # Carraige return
LF_CODE = chr(10).encode('ascii') # Line feed
CRLF = (chr(13) + chr(10)).encode('ascii')
OK_STR = "OK\r\n".encode('ascii')
CONNECT_STR = "CONNECT\r\n".encode('ascii')
RING_STR = "RING\r\n".encode('ascii')
FACTORY_RESET = "ATZ\r\n".encode('ascii')
RESET_PROFILE = "ATZ0\r\n".encode('ascii')
GET_MODEM_PRODUCT_CODE = "ATI0\r\n".encode('ascii')
GET_MODEM_SETTINGS = "AT&V\r\n".encode('ascii')
ECHO_OFF = "ATE0\r\n".encode('ascii')
ECHO_ON = "ATE1\r\n".encode('ascii')
ENABLE_FORMATTED_CID = "AT+VCID=1\r\n".encode('ascii')
ENABLE_VERBOSE_CODES = "ATV1\r\n".encode('ascii')
DISABLE_SILENCE_DETECTION = "AT+VSD=0,0\r\n".encode('ascii')
ENABLE_SILENCE_DETECTION_5_SECS = "AT+VSD=0,50\r\n".encode('ascii')
ENABLE_SILENCE_DETECTION_10_SECS = "AT+VSD=0,100\r\n".encode('ascii')
ENTER_VOICE_MODE = "AT+FCLASS=8\r\n".encode('ascii')
ENTER_VOICE_RECIEVE_STATE = "AT+VRX\r\n".encode('ascii')
ENTER_VOICE_TRANSMIT_STATE = "AT+VTX\r\n".encode('ascii')
ENTER_VOICE_TRANSMIT_RECIEVE_STATE = "AT+VTR\r\n".encode('ascii') # Start Voice Transmission and Reception (Voice Duplex)
SEND_VOICE_TONE_BEEP = "AT+VTS=[900,900,120]\r\n".encode('ascii') # 1.2 second beep
GET_VOICE_COMPRESSION_SETTING = "AT+VSM?\r\n".encode('ascii')
GET_VOICE_COMPRESSION_OPTIONS = "AT+VSM=?\r\n".encode('ascii')
SET_VOICE_COMPRESSION = "AT+VSM=1,8000,0,0\r\n".encode('ascii') # 1 = 8-bit unsigned pcm, 8.0 kHz
LINE_OFF_HOOK = "AT+VLS=1\r\n".encode('ascii') # DCE off-hook, connected to telco
LINE_ON_HOOK = "AT+VLS=0\r\n".encode('ascii') # DCE on-hook
TERMINATE_CALL = "ATH\r\n".encode('ascii')
# Modem DLE shielded codes - DCE to DTE modem data
DCE_ANSWER_TONE = (chr(16) + chr(97)).encode('ascii') # <DLE>-a
DCE_BUSY_TONE = (chr(16) + chr(98)).encode('ascii') # <DLE>-b
DCE_FAX_CALLING_TONE = (chr(16) + chr(99)).encode('ascii') # <DLE>-c
DCE_DIAL_TONE = (chr(16) + chr(100)).encode('ascii') # <DLE>-d
DCE_DATA_CALLING_TONE = (chr(16) + chr(101)).encode('ascii') # <DLE>-e
DCE_LINE_REVERSAL = (chr(16) + chr(108)).encode('ascii') # <DLE>-l
DCE_PHONE_ON_HOOK = (chr(16) + chr(104)).encode('ascii') # <DLE>-h
DCE_PHONE_OFF_HOOK = (chr(16) + chr(72)).encode('ascii') # <DLE>-H
DCE_PHONE_OFF_HOOK2 = (chr(16) + chr(80)).encode('ascii') # <DLE>-P
DCE_QUIET_DETECTED = (chr(16) + chr(113)).encode('ascii') # <DLE>-q
DCE_RING = (chr(16) + chr(82)).encode('ascii') # <DLE>-R
DCE_SILENCE_DETECTED = (chr(16) + chr(115)).encode('ascii') # <DLE>-s
DCE_TX_BUFFER_UNDERRUN = (chr(16) + chr(117)).encode('ascii') # <DLE>-u
DCE_END_VOICE_DATA_TX = (chr(16) + chr(3)).encode('ascii') # <DLE><ETX>
# System DLE shielded codes (single DLE) - DTE to DCE commands (used by USR 5637 modem)
DTE_RAISE_VOLUME = (chr(16) + chr(117)).encode('ascii') # <DLE>u
DTE_LOWER_VOLUME = (chr(16) + chr(100)).encode('ascii') # <DLE>d
DTE_END_VOICE_DATA_RX = (chr(16) + chr(33)).encode('ascii') # <DLE>!
DTE_END_VOICE_DATA_TX = (chr(16) + chr(3)).encode('ascii') # <DLE><ETX>
DTE_END_VOICE_DATA_TX_RX = (chr(16) + chr(94)).encode('ascii') # <DLE>^
DTE_CLEAR_TRANSMIT_BUFFER = (chr(16) + chr(24)).encode('ascii') # <DLE><CAN>
#=================================================================
# Initialize Modem
#=================================================================
def initialize_modem():
# Opean Serial Port
try:
line.open()
print ("Serial port open")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: Unable to open the Serial Port.")
sys.exit()
# Initialize
try:
line.reset_input_buffer()
line.reset_output_buffer()
# hang-up if opened
send(TERMINATE_CALL, OK_STR)
# reset to factory default.
send(FACTORY_RESET, OK_STR)
# Disable Command Echo Mode.
send(ECHO_OFF, OK_STR)
# Display result codes in verbose form
send(ENABLE_VERBOSE_CODES, OK_STR)
# Enable formatted caller report.
send(ENABLE_FORMATTED_CID, OK_STR)
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: unable to Initialize the Modem")
sys.exit()
#=================================================================
#=================================================================
# Execute AT Commands on the Modem
#=================================================================
def send(cmd, resp):
global modemResponse
result = False
try:
# Send command to the Modem
line.write(cmd)
print ("sent >:", cmd)
modemResponse = bytes("", 'ascii')
if (resp == ""):
return
timeout = time.time() + AT_RESPONSE_TIMEOUT
while (time.time() < timeout):
if (line.in_waiting != 0): # if response
modemResponse += line.read(line.in_waiting)
if (resp in modemResponse):
result = True
break
print ("rcvd <:", modemResponse)
modemResponse = bytes("", 'ascii')
# Failed command execution
if (result == False):
print ("Modem AT Command timeout")
sys.exit()
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: unable to write AT command to the modem: ", cmd)
sys.exit()
#=================================================================
#=================================================================
# Set Modem Voice Mode
#=================================================================
def set_voice_mod():
# Enter Voice Mode
send(ENTER_VOICE_MODE, OK_STR)
# Compression Method and Sampling Rate Specifications
# Compression Method: Unsigned PCM / Sampling Rate: 8000MHz
send(SET_VOICE_COMPRESSION, OK_STR)
# Open phone line
send(LINE_OFF_HOOK, OK_STR)
# Enable silence detection.
# Select normal silence detection sensitivity and a silence detection interval of 5 s.
send(ENABLE_SILENCE_DETECTION_5_SECS, OK_STR)
# Put modem into voice transmit receive mode
send(ENTER_VOICE_TRANSMIT_RECIEVE_STATE, CONNECT_STR)
#=================================================================
# Modem Data Listener
#=================================================================
def handle_line():
CHUNK = 256
global recStarted, recTimeout, recFile, audioFrames, playStarted, playFile, fileLen, chunkCounter, modemResponse, ringCount, ringTimeout
if (playStarted or recStarted):
if (playStarted):
if (chunkCounter < fileLen):
if (line.out_waiting < CHUNK):
line.write(playFile.readframes(CHUNK))
chunkCounter = chunkCounter + 1
else:
playFile.close()
playStarted = False
print ("Play Audio Msg - End")
if (recStarted):
if (line.in_waiting > 0):
# Read audio data from the Modem
audio_data = line.read(line.in_waiting)
# Check if <DLE>b is in the stream
if (DCE_BUSY_TONE in audio_data):
print ("Busy Tone... Call will be disconnected.")
# Check if <DLE>s is in the stream
elif (DCE_SILENCE_DETECTED in audio_data):
print ("Silence Detected... Call will be disconnected.")
# Check if <DLE><ETX> is in the stream
elif (DCE_END_VOICE_DATA_TX in audio_data):
print ("<DLE><ETX> Char Recieved... Call will be disconnected.")
else:
# Add Audio Data to Audio Buffer
audioFrames.append(audio_data) # .strip(' \t\n\r' + chr(16) + chr(3))
recFile.writeframes(b''.join(audioFrames))
audioFrames = []
if (time.time() > recTimeout):
# Save the Audio into a .wav file
recFile.close()
recStarted = False
# Send End of Voice Recieve state by passing "<DLE>^"
send(DTE_END_VOICE_DATA_TX_RX, DCE_END_VOICE_DATA_TX)
send(DCE_END_VOICE_DATA_TX, OK_STR)
print ("Record Audio Msg - End")
#Terminate the call
send(TERMINATE_CALL, OK_STR)
print ("Hang-up: Call ended")
return
# lineRXbuffer =
if (line.in_waiting > 0):
modemResponse += line.read(line.in_waiting)
if (len(modemResponse) != 0):
print ("rcvd <:", modemResponse)
if (DCE_BUSY_TONE in modemResponse): #3 busy tone
#Terminate the call
print ("Busy Tone: Call Terminated")
send(TERMINATE_CALL, OK_STR)
elif (DCE_SILENCE_DETECTED in modemResponse): #3 silence
#Terminate the call
print ("Silence: Call Terminated")
send(TERMINATE_CALL, OK_STR)
elif (RING_STR in modemResponse): # or ("DATE" in modemResponse) or ("TIME" in modemResponse) or ("NMBR" in modemResponse):
modemResponse = bytes("", 'ascii')
ringTimeout = time.time() + RING_TIMEOUT
ringCount = ringCount + 1
if (ringCount == ANSWER_AFTER_RINGS):
print ("Ring: Call Started")
ringTimeout = 0
ringCount = 0
set_voice_mod()
# Play Audio File
playFile = wave.open('sample.wav','rb')
fileLen = playFile.getnframes() / CHUNK
chunkCounter = 0
playStarted = True
print ("Play Audio Msg - Start")
# Record Audio File
recFile = wave.open('record.wav', 'wb')
recFile.setnchannels(1)
recFile.setsampwidth(1)
recFile.setframerate(8000)
recTimeout = time.time() + MAX_REC_DURATION
audioFrames = []
print ("Record Audio Msg - Start")
recStarted = True
if ((ringTimeout != 0) and (time.time() > ringTimeout)): # new ring did not come before play_audio
ringTimeout = 0
ringCount = 0
modemResponse = bytes("", 'ascii')
#=================================================================
#=================================================================
# Close the Serial Port
#=================================================================
def close_modem_port():
send(TERMINATE_CALL, OK_STR)
try:
if line.is_open:
line.close()
print ("Serial Port closed...")
except Exception as err:
print(f"Unexpected {err=}, {type(err)=}")
print ("Error: Unable to close the Serial Port.")
sys.exit()
#=================================================================
try:
os.remove('record.wav')
except OSError:
pass
initialize_modem()
atexit.register(close_modem_port)
while(True):
handle_line()
time.sleep(0.01)
I'm a trying to start a program at boot but without success.
The program starts well but doesn't stay alive (it is supposed to be a infinite script).
But when I start the program normally I don't have any problem! I don't get why when I run at reboot it doesn't work.
I use a cron tab like this:
#reboot sudo python /bin/gestion.py &
I can show you my code:
import Adafruit_BBIO.GPIO as GPIO
import Adafruit_BBIO.PWM as PWM
import time
import socket
import threading
import sys
from os.path import expanduser
import datetime
print("DEBUT")
vitesse = 4
etat_moteur_droit = 0
etat_moteur_gauche = 0
data_thr = "Starting"
etat_thr = 1
HOST = '192.168.1.50' # Standard loopback interface address (localhost)
PORT = 65432 # Port to listen on (non-privileged ports are > 1023)
file = open('/home/log.txt', 'w')
file.write("It worked!\n" + str(datetime.datetime.now()))
file.close()
print("MID")
def main():
global data_thr
global etat_thr
global etat_moteur_droit
global etat_moteur_gauche
global vitesse
print("START")
etat_moteur_droit=0
setup_io()
# gestion_bonus(0)
# gestion_moteur_droit(4,0)
# gestion_moteur_gauche(4,0)
# avancer()
# time.sleep(3)
# tourner_a_gauche()
# time.sleep(3)
# tourner_a_droite()
# time.sleep(3)
# arreter()
x = threading.Thread(target=thread_serveur)
x.start()
while True:
try:
data_thr = data_thr.partition('\n')[0]
if(data_thr == ""):
etat_thr = 0
if(data_thr == "Fin thread"):
x = threading.Thread(target=thread_serveur)
x.start()
data_thr = "Fin thread step 2"
if(data_thr == "avance"):
avancer()
if(data_thr == "stop"):
arreter()
if(data_thr == "gauche"):
tourner_a_gauche()
if(data_thr == "droite"):
tourner_a_droite()
if(data_thr[:7] == "vitesse"):
vitesse = int(data_thr[8:10])
if(etat_moteur_droit == 1):
PWM.set_duty_cycle("P9_14", vitesse)
if(etat_moteur_gauche == 1):
PWM.set_duty_cycle("P8_19", vitesse)
except:
print("Erreur lors de reception message")
print("FIN")
file = open('/home/log.txt', 'w')
file.write("FIN!\n" + str(datetime.datetime.now()))
file.close()
def thread_serveur():
global data_thr
global etat_thr
connected = 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)
while connected == 0:
try :
s.bind((HOST, PORT))
except socket.error:
pass
finally:
connected = 1
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
timing = 0
start = time.time()
while etat_thr == 1:
try:
data_thr = conn.recv(1024)
if not data_thr:
break
if data_thr != "":
print(data_thr)
conn.sendall("Bien recu")
except:
print("Erreur lecture thread")
s.shutdown(socket.SHUT_RDWR)
s.close()
data_thr = "Fin thread"
def setup_io():
GPIO.setup("P9_17", GPIO.OUT)
GPIO.setup("P9_24", GPIO.OUT)
GPIO.setup("P9_23", GPIO.OUT)
PWM.start("P9_14", 0)
PWM.stop("P9_14")
PWM.start("P8_19", 0)
PWM.stop("P8_19")
PWM.cleanup()
def gestion_bonus(etat):
if(etat == 1):
GPIO.output("P9_17", GPIO.HIGH)
else:
GPIO.output("P9_17", GPIO.LOW)
GPIO.cleanup()
def gestion_moteur_droit(vitesse,enable):
global etat_moteur_droit
if(enable == 1 and etat_moteur_droit == 0):
PWM.start("P9_14", vitesse)
GPIO.output("P9_24",GPIO.HIGH)
etat_moteur_droit = 1
elif(enable == 1 and etat_moteur_droit == 1):
PWM.set_duty_cycle("P9_14", vitesse)
GPIO.output("P9_24",GPIO.HIGH)
elif(enable == 0):
PWM.stop("P9_14")
GPIO.output("P9_24",GPIO.LOW)
etat_moteur_droit =0
GPIO.cleanup()
def gestion_moteur_gauche(vitesse,enable):
global etat_moteur_gauche
if(enable == 1 and etat_moteur_gauche == 0):
PWM.start("P8_19", vitesse)
GPIO.output("P9_23",GPIO.HIGH)
etat_moteur_gauche = 1
elif(enable == 1 and etat_moteur_gauche == 1):
PWM.set_duty_cycle("P8_19", vitesse)
GPIO.output("P9_23",GPIO.HIGH)
elif(enable == 0):
PWM.stop("P8_19")
GPIO.output("P9_23",GPIO.LOW)
etat_moteur_gauche =0
GPIO.cleanup()
def avancer():
global vitesse
gestion_moteur_droit(vitesse,1)
gestion_moteur_gauche(vitesse,1)
def tourner_a_gauche():
global vitesse
gestion_moteur_droit(vitesse,1)
gestion_moteur_gauche(vitesse,0)
def tourner_a_droite():
global vitesse
gestion_moteur_droit(vitesse,0)
gestion_moteur_gauche(vitesse,1)
def arreter():
global vitesse
gestion_moteur_droit(vitesse,0)
gestion_moteur_gauche(vitesse,0)
if __name__ == "__main__":
main()
Can you help me please?
As I can see you are using some network service. Maybe when the cron run at #reboot, the network is not ready yet. It may worth a try to implement as service and run command on that way.
Example implementation
Create a file where the system daemon services can be found, e.g.: /lib/systemd/system/TestStartup.service. Example for content of member:
[Unit]
Description=Test service for startup
After=network.target
[Service]
User=root
ExecStart=/usr/bin/python /bin/gestion.py
Restart=on-failure
RestartSec=30
[Install]
WantedBy=multi-user.target
/usr/bin/pythn can be different as which version you are using and where it is installed on your machine, but you can check by whereis python command output:
ati#atihome:/lib/systemd/system$ whereis python
python: /usr/bin/python2.7 /usr/bin/python /usr/bin/python3.7 /usr/bin/python3.7m /usr/lib/python2.7 /usr/lib/python3.7 /etc/python2.7 /etc/python /etc/python3.7 /usr/local/lib/python2.7 /usr/local/lib/python3.7 /usr/share/python /usr/share/man/man1/python.1.gz
Then you need to reload system daemon and enable this service to allow to run after system startup. This service will start after Network is up. You can do by these commands:
systemctl daemon-reload
systemctl enable TestStartup (or how you named your member)
You can test, that start command is proper by this command:
systemctl start TestStartup
And check its status by this command:
systemctl status TestStartup
Then you can reboot the computer and check that it worked. I don't say that is is your solution for 100% but it may worth a try.
This question is a follow-up of this topic.
The OP was very likely encountering "Connection Refused". I'm facing it now with the same
code:
#!/usr/bin/env python3
import sys, socket, subprocess, threading, getopt
listen = False
upload = False
command = False
execute = ''
target = ''
upload_dest = ''
port = 0
USAGE = '''
BHP Net Tool
Usage: bhpnet.py -t target_host -p port
-l --listen - listen on [host]:[port] for incoming
connections
-e --execute=file_to_run - execute the given file upon receiving
a connection
-c --command - initialize a command shell
-u --upload=destination - upon receiving connection upload a file
and write to [destination]
Examples:
bhpnet.py -t 192.168.0.1 -p 5555 -l -c
bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe
bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\"
echo "ABCDEF" | ./bhpnet.py -t 192.168.11.12 -p 135
'''
def usage():
print(USAGE)
sys.exit(0)
def main():
global listen
global port
global execute
global command
global upload_dest
global target
if not len(sys.argv[1:]):
usage()
try:
opts, args = getopt.getopt(sys.argv[1:], 'hle:t:p:cu:',['help','listen',
'execute','target','port','command','upload'])
except getopt.GetoptError as err:
print(str(err))
usage()
for o, a in opts:
if o in ('-h', '--help'):
usage()
elif o in ('-l', '--listen'):
listen = True
elif o in ('-e', '--execute'):
execute = a
elif o in ('-c', '--commandshell'):
command = True
elif o in ('-u', '--upload'):
upload_dest = a
elif o in ('-t', '--target'):
target = a
elif o in ('-p', '--port'):
port = int(a)
else:
assert False, 'Unhandled Option'
if not listen and len(target) and port > 0:
buffer = sys.stdin.read()
client_sender(buffer)
if listen:
server_loop()
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
client.connect((target, port))
if len(buffer):
client.send(buffer)
while True:
recv_len = 1
response = ''
while recv_len:
data = client.recv(4096)
recv_len = len(data)
response += data
if recv_len < 4096:
break
print(response)
buffer = input('')
buffer += '\n'
client.send(buffer)
except Exception as e:
print(e) # here it prints out "Connection Refused"
print('[*] Exception ! Exiting ...')
client.close()
def server_loop():
global target
if not len(target):
target = '0.0.0.0'
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
while True:
client_socket, addr = server.accept()
client_thread = threading.Thread(target=client_handler, args=(client_socket,))
client_thread.start()
def run_command(command):
command = command.rstrip()
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
output = 'Failed to execute command.\r\n'
return output
def client_handler(client_socket):
global upload
global execute
global command
if len(upload_dest):
file_buffer = ''
while True:
data = client_socket.recv(1024)
if not data:
break
else:
file_buffer += data
try:
with open(upload_dest, 'wb') as file_descriptor:
file_descriptor.write(file_buffer)
client_socket.send(b'Successfully saved file to {}.'.format(upload_dest))
except:
client_socket.send(b'Failed to save file to {}'.format(upload_dest))
if len(execute):
output = run_command(execute)
client_socket.send(output)
if command:
while True:
client_socket.send(b'<BHP:#> ')
cmd_buffer = ''
while '\n' not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
response = run_command(cmd_buffer)
client_socket.send(response)
main()
I'd like to ask more experienced network professsional why it could possibly throw "Connection Refused" if the port 9999 is open and firewall isn't blocking it ?
Running it like this:
server-side: ./netcat_repl.py -l -p 9999 -c
client-side: ./netcat_repl.py -t localhost -p 9999
I am playing around with a little netcat tool of my own, but I keep getting "Connection refused" and a reference to a specific line, I've highlighted that below.
First I run the server, with the following command:
python Netstatx.py -l -p 9999 -c
Then I run the "client" which tries to make a connection to the server, which is listening on port 9999:
python Netstatx.py -t localhost -p 9999
As mentioned, the above gives me an "Connected refused"-exception, how come?
import sys
import socket
import getopt
import threading
import subprocess
# Define globals
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0
def usage():
print "Netstatx - Net Tool for your convenience"
print
print "Usage: Netstatx.py -t target_host -p port"
print "-l --listen - Listen on [host]:[port] for
incoming connections"
print "-e --execute=file_to_run - Execute the given file upon
receiving a connection"
print "-c --command - Initialize a command shell"
print "-u --upload=destination - Upon receiving connection,
upload a file and write to
[destination]"
print
print
print "Examples: "
print "Netstatx.py -t 192.168.0.1 -p 5555 -l -c"
print "Netstatx.py -t 192.168.0.1 -p 5555 -l -u=\\target.exe"
print "Netstatx.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
sys.exit(0)
def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "%s:%s" % (target, port)
# Connect to our target host
**client.connect((target, port))** <-- This is failing.
if len(buffer):
client.send(buffer)
while True:
# Now wait for data back
recv_len = 1
response = ""
while recv_len:
data = client.recv(4096)
recv_len = len(data)
response += data
if recv_len < 4096:
break
print response,
# Wait for more input
buffer = raw_input("")
buffer += "\n"
# Send it off
client.send(buffer)
def server_loop():
global target
# If no target is defined, we listen on all interfaces
if not len(target):
target = "0.0.0.0"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
while True:
client_socket, addr = server.accept()
# Spin off a thread to handle our new client
client_thread = threading.Thread(target=client_handler,
args=(client_socket,))
client_thread.start()
def main():
global listen
global port
global execute
global command
global upload_destination
global target
if not len(sys.argv[1:]):
usage()
# Read the commandline options
try:
opts, args = getopt.getopt(sys.argv[1:], "hle:t:p:cu:",
["help","listen","execute","target","port","command",
"upload"])
except getopt.GetoptError as err:
print str(err)
usage()
for o,a in opts:
if o in ("-h", "--help"):
usage()
elif o in ("-l", "--listen"):
listen = True
elif o in ("-e", "--execute"):
execute = a
elif o in ("-c", "--commandshell"):
command = True
elif o in ("-u", "--upload"):
upload_destination = a
elif o in ("-t", "--target"):
target = a
elif o in ("-p", "--port"):
port = int(a)
else:
assert False, "Unhandled option!"
# Are we going to listen or just send data?
# if not listen and len(target) and port > 0
# Read in the buffer from the commandline
# this will block, so send CTRL-D if not sending input
# to stdin
buffer = sys.stdin.read()
# Send data off
client_sender(buffer)
# We are going to listen and potentially
# upload things, execute commands, and drop a shell back
# depending on our command line options above
if listen:
server_loop()
main()
def run_command(command):
# trim the newline
command = command.rstrip()
# Run the command and get the output back
try:
output = subprocess.check_output(command,
stderr=subprocess.STDOUT, shell=True)
except:
output = "Failed to execute command. \r\n"
# Send the output back to the client return output
return output
def client_handler(client_socket):
global upload
global execute
global command
# Check for upload
if len(upload_destination):
# Read on all of the bytes and write to our destination
file_buffer = ""
# Keep reading data until none is available
while True:
data = client_socket.recv(1024)
if not data:
break
else:
file_buffer += data
# Now we take these bytes and try to write them out
try:
file_descriptor = open(upload_destination, "wb")
file_descriptor.write(file_buffer)
file_descriptor.close()
# Acknowledge that we rote the file out
client_socket.send("Successfully saved file to %s\r\n" %
upload_destination)
except:
client_socket.send("Failed to save file to %s\r\n" %
upload_destination)
# Check for command execution
if len(execute):
# Run the command
output = run_command(execute)
client_socket.send(output)
# Now we go into another loop if a command shell was requested
if command:
while True:
# Show a simple prompt
client_socket.send("<Netstatx:#> ")
# Now we receive until we see a linefeed (enter key)
cmd_buffer = ""
while "\n" not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
# Send back the command output
response = run_command(cmd_buffer)
# Send back the response
client_socket.send(response)
import sys
import socket
import getopt
import threading
import subprocess
#define some global variables
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0
def usage():
print "Net Tool"
print
print "Usage : netcat.py -t target_host -p port"
print "-l --listen -listen on [host]:[port] for incoming connections"
print "-e --execute=file_to_run -execute the given file upon receiving a connection "
print "-c --command -intialize a command shell"
print "-u --upload=destination -upon receiving connection upload a file and write to [destination]"
print
print
print "Examples : "
print "netcat.py -t 192.168.0.1 -p 5555 -l -c"
print "netcat.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"
print "netcat.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
print "echo 'ABCDEEGHI' | ./netcat.py -t 192.168.11.12 -p 135"
sys.exit(0)
def run_command(command):
#trim the newline
command= command.rstrip()
#run the command get the output back
try:
output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
except:
output = "Failed to execute command.\r\n"
#send the output back to the client
return output
def client_handler(client_socket):
global upload
global execute
global command
#check for upload
if len(upload_destination):
#read in all of the bytes and write to our destination
file_buffer= ""
#keep reading data until none is available
while True:
data= client.socket.recv(1024)
if not data:
break
else:
file_buffer += data
#now we take these bytes and try to write them out
try:
file_descriptor=open(upload_destination,"wb")
file_descriptor.write(file_buffer)
file_descriptor.close()
#aknowledg that we wrote the file out
client_socket.send("Successfully saved file to %s \r\n" % upload_destination)
except:
client_socket.send("Failed to save file to %s \r\n" % upload_destination)
# check for command execution
if len(execute):
# run the command
output = run_command(execute)
client_socket.send(output)
# now we go into another loop if a command shell was requested
if command:
while True:
# show a simple prompt
client_socket.send("<BHP:#> ")
# now we receive until we see a linefeed (enter key)
cmd_buffer = ""
while "\n" not in cmd_buffer:
cmd_buffer += client_socket.recv(1024)
# send back the command output
response = run_command(cmd_buffer)
# send back the response
client_socket.send(response)
def client_sender(buffer):
client= socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
#connect to our target host
client.connect((target,port))
if len(buffer):
client.send(buffer)
while True:
#now wait for data back
recv_len=1
response=""
while recv_len:
data = client.recv(4096)
recv_len= len(data)
response+=data
if recv_len<4096:
break
print response,
#wait for more input
buffer = raw_input("")
buffer+= "\n"
# send it off
client.send(buffer)
except:
print "[*] Exception! Exiting."
client.close()
def server_loop():
global target
#if no target is defined , we listen on all interfaces
if not len(target):
target ="0.0.0.0"
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target, port))
server.listen(5)
while True:
client_socket, addr = server.accept()
#spin off a thread to handl our new client
client_thread= threading.Thread(target=client_handler, args=(client_socket,))
client_thread.start()
def main():
global listen
global port
global execute
global command
global upload_destination
global target
if not len(sys.argv[1:]):
usage()
#read the commandline options
try:
opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu",["help","listen","execute","target","port","command","upload"])
except getopt.GetoptError as err:
print str(err)
usage()
for o,a in opts:
if o in ("-h", "--help"):
usage()
elif o in ("-l","--listen"):
listen=True
elif o in ("-e", "--execute"):
execute =a
elif o in ("-c", "--commandshell"):
command= True
elif o in ("-u", "--upload"):
upload_destination = a
elif o in ("-t", "--target"):
target =a
elif o in ("-p", "--port"):
port=int(a)
else :
assert False, "unhandled option"
# are we going to listen or just send data from stdin?
if not listen and len(target) and port> 0 :
#read in the buffer from the cmdline
#this will block, so send CTRL-D if not sending input
#to stdin
buffer = sys.stdin.read()
client_sender(buffer)
#we are goin to listen and potentially
#upload things, execute commands, and drop a shell back
#depending on our command line options above
if listen :
server_loop()
main()
I found some syntax errors running out your script ( it may be just from copy past), any way i did my small edits and it's working (knowing i'm under linux)
Your problem may be the firewall is refusing connection on that port, try to check it out