Python - socket CAN connection - python

I am using python to receive data from Linux socket CAN.
ID is 0x1f7d8401, whereas the ID of the data I received was 401, showing only the last three digits.
What should I modify to get the whole ID value except 0x?
Attached is the source code.
import can
import time
import os
print('\n\rCAN Rx test')
print('Bring up CAN0....')
os.system("sudo /sbin/ip link set can0 up type can bitrate 500000")
time.sleep(0.1)
try:
bus = can.interface.Bus(channel='can0', bustype='socketcan_native')
except OSError:
print('Cannot find PiCAN board.')
exit()
print('Ready')
try:
while True:
message = bus.recv() # Wait until a message is received.
c = '{0:f} {1:x} {2:x} '.format(message.timestamp, message.arbitration_id, message.dlc)
s=''
for i in range(message.dlc ):
s += '{0:x} '.format(message.data[i])
print(' {}'.format(c+s))
except KeyboardInterrupt:
#Catch keyboard interrupt
os.system("sudo /sbin/ip link set can0 down")
print('\n\rKeyboard interrtupt')

I just copied your code for testing, but with vcan0, instead of can0. It works fine.
Able to receive full address. I don't know how you are sending data.
I used cansend vcan0 1f7d8401#data. (No '0x' prefix for canid, here).

Related

Infinite loading on conn.recv python socket

I'm currently trying to make a socket connection between a server and multiple clients in Python.
In short, I have a function that is used to test if the clients are still online or dead.
To do so, i'm sending a white space to the client, and if no exception occures, it's all good, and if there is an exception I'm deleting the client from the client list.
Everything works fine, except when the client is switching network (for exemple I switch from a 2GHz network, to the same network in 5GHz). Then, the conn.recv is creating an infinite loading because the client is not receiving the data that was sent in conn.send. As a precision, both of the network where I was connected works well separately. The only solution that I found for now is restarting the server when such an event occurs..
Here is the part of the code that doesn't work (server):
# Check for clients availability
def check_clients(self, UUID):
invalid_conn = []
print(f"(UUID: {UUID}) Checking for dead clients")
if UUID not in self.all_connections: return False
# Delete dead clients for specific user (UUID)
self.socket.settimeout(2) # Also tried to set a timeout, doesn't work
print('setting timeout')
for i, conn in enumerate(self.all_connections[UUID]):
try:
print('sending blank cmd')
conn.send(str.encode(' '))
cwd = str(conn.recv(20480)) # This is the line that causes infinite loop
print('got cwd:',cwd) # This is what we are excepting from the client
except:
print('appening invalid conn to list:',conn)
invalid_conn.append(conn)
continue
print('removing timeout')
self.socket.settimeout(None)
for i in invalid_conn:
client_id = self.all_connections[UUID].index(i)
print(f'(UUID: {UUID}) Could not reach client on conn list, removing {self.all_addresses[UUID][client_id]}')
del self.all_connections[UUID][client_id]
del self.all_addresses[UUID][client_id]
print(f"(UUID: {UUID}) Dead clients check finished")
return
And here is the part of the client that should receive the server information:
# Receive commands from server
def receive_commands(self):
while True:
print("Listening for commands")
output_str = None
data = self.sock.recv(1024)
print('data:',data)
if len(data) > 0:
try:
cmd = data[:].decode("cp850")
# Do such and such events with cmd, this is a shortened version for demo
output_str = str(f'received: {cmd} from server', "cp850")
except Exception as e:
output_str = f"Command failed to execute: {str(e)}"
if output_str == None:
raise ConnectionError ("No response from server")
else:
self.print_output(output_str)
print(f"Input command: {data[:].decode('cp850')}")
print(f"Output -> {output_str}\n")
self.sock.close()
return
Please ask me if you need any more info, thank you for your help.

How can I get python to trigger a process based on an incoming string from serial listening?

Totally new to Python. Working with a Paspberry Pi and Rockblock 2 satellite SBD transceiver connected over FTDI cable. Have managed enough python code to listen to the rockblock to catch a SBDRING trigger. Once received I need it to recognise this so I can try to get it to take an action. My code here fails to trigger and just keeps listening. Is there some rule or reason I've not been able to find as to why the python equalto won't work on what is being listened to?
import time
import serial
port = "/dev/ttyUSB0"
ser = serial.Serial(port, baudrate=19200, timeout=5)
print "Starting monitor of '" + port + "'"
try:
ser.isOpen()
print(port + " is open")
except:
print("Error")
exit()
if(ser.isOpen()):
try:
while(1):
print(ser.readline())
if(ser.readline() == "SBDRING"):
print "Message detected!"
except Exception:
print("Error reading serial")
else:
print("Cannot open '" + port + "'")
Expected result: on display a new line ticks over every 5 seconds. When "SBDRING" appears it should be followed by "Message detected!" and carrying on.
Actual result: on display a new line ticks over every 5 seconds. When "SBDRING" appears it does not displays "Message detected!", just carries on.
I intend to replace the 'print "Message detected!"' part with a actual action once it functions.
Maybe the string you're expecting includes a terminating character like a CR or LF.
You should print what you get from the port and study its length.
Otherwise, you can loosen a bit your comparison, maybe something like:
if("SBDRING" in ser.readline()):
print "Message detected!"
EDIT: Looking at the manual, it seems the device terminates everything with "\r" so I guess you should manage with:
if(ser.readline() == "SBDRING\r"):
print "Message detected!"

How to make calls with GSM modem using python

I am trying to use gsmmodem-new on python to make calls from attached gsm modem. The modem is connected on serial com 1 and the baud rate is set at 115200. Sim card has no PIN code enabled.
I am simply trying to use the example provided by the developers
#!/usr/bin/env python
"""\
Demo: dial a number (simple example using polling to check call status)
Simple demo app that makes a voice call and plays sone DTMF tones (if
supported by modem)
when the call is answered, and hangs up the call.
It polls the call status to see if the call has been answered
Note: you need to modify the NUMBER variable for this to work
"""
from __future__ import print_function
import sys, time, logging
from hashlib import new
PORT = 'COM1'
BAUDRATE = 115200
NUMBER = '6973233298' # Number to dial - CHANGE THIS TO A REAL NUMBER
PIN = None # SIM card PIN (if any)
waitingForModemToRespondInSeconds = 10
from gsmmodem.modem import GsmModem
from gsmmodem.exceptions import InterruptedException, CommandError
def main():
if NUMBER == None or NUMBER == '00000':
print('Error: Please change the NUMBER variable\'s value before
running this example.')
sys.exit(1)
print('Initializing modem...')
logging.basicConfig(format='%(levelname)s: %(message)s',
level=logging.DEBUG)
modem = GsmModem(PORT, BAUDRATE)
modem.connect(PIN,waitingForModemToRespondInSeconds)
print('Waiting for network coverage...')
modem.waitForNetworkCoverage(30)
print('Dialing number: {0}'.format(NUMBER))
call = modem.dial(NUMBER)
print('Waiting for call to be answered/rejected')
wasAnswered = False
while call.active:
if call.answered:
wasAnswered = True
print('Call has been answered; waiting a while...')
time.sleep(3.0)
print('Playing DTMF tones...')
try:
if call.active: # Call could have been ended by remote party while we waited in the time.sleep() call
call.sendDtmfTone('9515999955951')
except InterruptedException as e:
# Call was ended during playback
print('DTMF playback interrupted: {0} ({1} Error {2})'.format(e, e.cause.type, e.cause.code))
except CommandError as e:
print('DTMF playback failed: {0}'.format(e))
finally:
if call.active: # Call is still active
print('Hanging up call...')
call.hangup()
else: # Call is no longer active (remote party ended it)
print('Call has been ended by remote party')
else:
# Wait a bit and check again
time.sleep(0.5)
if not wasAnswered:
print('Call was not answered by remote party')
print('Done.')
modem.close()
if __name__ == '__main__':
main()
but the process stucks when a connection is trying to be established with the modem. It seems that it cannot connect to the modem in order to proceed to the next steps.
Can someone please help me?

Receiving "NO CARRIER" error while tring to make a call using GSM modem in Python

I want to make a call using my GSM modem. So I wrote the below program:
import time
import serial
recipient = "+98xxxxxxxxxx"
phone = serial.Serial("COM10", 115200, timeout=5)
try:
time.sleep(0.5)
phone.write(b'ATZ\r')
time.sleep(1)
phone.write(b'ATD"'+recipient.encode() +b'"\r')
while(1):
print(phone.readline())
time.sleep(0.5)
finally:
phone.close()
But when I run it I receive this output:
>>> ================================ RESTART ================================
>>>
b'ATZ\r\r\n'
b'OK\r\n'
b'ATDxxxxxxxxxx\r\r\n'
b'NO CARRIER\r\n'
What does this "NO CARRIER" error means?
Note that I can send SMS successfully.
This is the program that I use to send SMS:
import time
import serial
recipient = "+98xxxxxxxxxx"
message = "Test"
phone = serial.Serial("COM10", 115200, timeout=5)
try:
time.sleep(0.5)
phone.write(b'ATZ\r')
time.sleep(0.5)
phone.write(b'AT+CMGF=1\r')
time.sleep(0.5)
phone.write(b'AT+CMGS="' + recipient.encode() + b'"\r')
time.sleep(0.5)
phone.write(message.encode() + b"\r")
time.sleep(0.5)
phone.write(bytes([26]))
time.sleep(0.5)
finally:
phone.close()
I found the origin of the error :
The syntax is ATD+98xxxxxxxxxx; followed by terminating string. I was forgotten to put semicolon at the end after the number.
So I replace
phone.write(b'ATD"'+recipient.encode() +b'"\r')
with
phone.write(b'ATD"'+recipient.encode() +b';"\r')
And now it works fine.
Based on the brackets in this documents, I thought that using ";" is optional. But it seems that I was wrong.

Client socket not receiving data correctly

I've tried looking about for an answer but I can't seem to find one that answers my specific problem.
Perhaps I don't know how to articulate the problem correctly.
I think I've pinpointed what it is, but the thing is I just don't know how to fix it.
EDIT: I was trying to use two clients on one TCP Socket. Can't do that. I'll have to think of another way. Solved, I guess.
So what I've got is are
1: Two Clients
2: One Server
The objective is this:
Have the server distribute new usernames to all the clients as they connect.
This is what happens when I run the program:
Server: Define Host, and Port, initialize it. Check
Client 1: Connects to the server. Check
Client 1: Once connected, sends a string to the server. Check
Server: Receives a string, checks if the string is in a list is created. If it is: Pass, if it's not, send to everyone the new string. Check
Client 1: [Now waiting to receive data] Recieves data, checks if the string received matches the one it sent. If it does, print("It's one of ours!"), else, make the new string = to Client 2 Username. Check
Client 2: Connects to server: Check
Server: [If it receives a string, prints it.] (Works) Checks if the new string is in the list. [It isn't] So It sends the new username to everyone, and then prints ("Sent to everyone") Check
But, when client 2 receives the string, it prints it. However, client 1 never recives the string.
And when running client one in IDLE, I noticed something went wrong as Client 1 tried to receive the data. (The while loop that the data = s.recv began looping real fast, instead of waiting)
I've asked around in chat, but it seems nobody's around right now. I've tried looking this up but I really can't find an answer. What I suspect is happening is that when my server sends to 'connection' the second time, it somehow overrides the original client connection.
Here's my server code:
from socket import *
import threading
import os
import csv
Username_List = []
host = input("Host: ")
port = input("Port: ")
ss = socket(AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
ss.listen(2)
while True:
try:
connection,address = ss.accept()
data = connection.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data in Username_List:
pass
else:
Username_List.append(translated_data)
connection.sendall(translated_data.encode())
print("Sent new username to everyone")
except IOError:
connection.close()
print("An exception with a connected user occured")
break
And here is my client code: [The only difference between client 1 and 2 is I changed the username variable]
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("Owatch")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket(AF_INET,SOCK_STREAM)
ss.connect((host,int(port)))
except IOError:
print("Aw no man")
ss.send(Username.encode())
while True:
try:
print("Waiting to Recieve Data")
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print("It's one of ours!")
else:
Client_Username = translated_data
print (Client_Username)
except Exception as e:
print (vars(e))
If you could please help I'd be grateful.
If you know of an answer to my question that's already been asked, please tell me and I'll remove this post to avoid breaking rules. Thanks!
Right then I started with what you had then changed it till it worked what I've done is created a client class which starts a thread with each connection and adds it to a list of threads (please if I'm doing something horribly wrong smarter people correct me), the thread runs gets some data checks if that's in the list of user names if its not sends out a message to all the clients in the thread list with that name then the thread just chills out. Anyway on to the code.
SERVER!!!
import csv
class client(threading.Thread):
Username_List = []
def __init__(self, conn):
super(client, self).__init__()
self.conn = conn
def run(self):
print "Client thread started"
data = self.conn.recv(1024)
print "Received: {0}".format(data)
if data in client.Username_List:
self.send_msg("Welcome Back!")
else:
for cnt in threadz:
cnt.send_msg(data)
print("Sent new username to everyone")
client.Username_List.append(data)
while True:
# dont need nothing now
pass
def send_msg(self,msg):
self.conn.send(msg)
host = input("Host: ")
port = input("Port: ")
ss = socket() #AF_INET,SOCK_STREAM)
ss.bind((host,int(port)))
print "Server Opening on port: {0}".format(port)
ss.listen(2)
threadz = []
print "Begining Wait for connections"
while True:
try:
connection, address = ss.accept()
print "Got ONE!"
c = client(connection)
print "Recevied connection from:{0} On port:{1}".format(address[0],address[1])
c.start()
threadz.append(c)
print "Client appended to threadz, currently {0} threadz active".format(len(threadz))
except IOError,KeyboardInterrupt:
connection.close()
print("An exception with a connected user occured")
break
The CLIENT:
# Sample Username Client Service Handler.
from socket import *
import threading
import os
import csv
Username = ("ShyGuy")
host = input("Host: ")
port = input("Port: ")
try:
ss = socket() #AF_INET,SOCK_STREAM)
ss.connect((host,int(port))) #I was using ("localhost",1234) for testing
ss.send(Username)
except IOError:
print("Aw no man")
print("Waiting to Recieve Data")
while True:
try:
data = ss.recv(1024)
if data:
translated_data = data.decode()
print(translated_data)
if translated_data == Username:
print"Name: {0} has been registered on server!".format(translated_data)
else:
Client_Username = translated_data
print "New client name received: {0}".format(Client_Username)
except Exception as e:
print (vars(e))
That works on python 2.7 with two clients locally. Needs to use a semaphore to stop the threads printing at the same time as the main server loop prints: http://en.wikipedia.org/wiki/Semaphore_(programming)
This code does nothing graceful with client disconnects, but once you can work with the exceptions that a raised when that happens I'm sure you'll learn some more.

Categories

Resources