Manual
do
Maker
.
com
Os artigos posteriores serão bastante relacionados a rede, de modo que se fará necessário um certo apoio para testar as implementações. Nada mais fácil do que fazer um socket server com Python para esses testes, uma vez que, além de ser multiplataforma, é fácil e rápido de implementar. Se não quiser fazer nada em seu sistema nativo, pode optar por criar um virtualenv para esses testes.
Imagine que você precise implementar uma comunicação socket em algum embarcado. A parte essencial de qualquer implementação é a capacidade de testar o que está sendo implementado. Implementar simultaneamente as duas "pontas" da comunicação pode ser caótico, pois em caso de falha fica difícil determinar em qual dos dois lados estará o problema. Executando um socket server local nos garante ter um lado da comunicação garantida e o melhor - poderemos ler os dados como chegam, para no fim fazer a melhor implementação possível.
Uma sugestão (e opinião pessoal) é que não devemos nos ater a uma só linguagem. Se você só programa em C ou C++, acabará ficando refém de uma solução de terceiros, sem a garantia de que ela seja funcional ou adequada (ou até ambos) para seu projeto. Programo relativamente bem em Python desde 2009 (já programei melhor, quando fazia parte do meu dia-a-dia), assim como programo bem o suficiente em C, C++ e Qt (sendo que Qt também não faz mais parte do meu dia-a-dia). Além disso, tenho uma boa habilidade em shellscript (em Linux), e essas linguagens me permitem criar soluções completas multiplataforma e em diversos níveis de serviço. E para quem programa em C/C++, Python acaba sendo extremamente mais simples, como a exemplo desse socket server:
import socket
s = socket.socket()
s.bind(('0.0.0.0', 8888 ))
s.listen(0)
while True:
client, addr = s.accept()
while True:
content = client.recv(32)
if len(content) == 0:
break
else:
print(content)
print("Fim da conexao")
client.close()
Para testar seu socket server com Python, crie um socket client com a mesma simplicidade:
#!/usr/bin/env python
import socket
#ip a se conectar
ip = "192.168.1.200"
#porta do socket server
port = 8888
addr = ((ip,port))
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(addr)
msg = "hell low word"
client_socket.send(msg.encode('UTF-8'))
client_socket.close()
E o resultado deve ser semelhante a esse:
Agora é só acompanhar os próximos artigos relacionados - e deixo o convite para inscrever-se em nosso canal DobitaobyteBrasil no Youtube, com nosso formato de áudio e vídeo, para uma melhor experiência!
Teremos alguns vídeos relacionados à comunicação socket, acredito que vale experimentar.
Reparou que o resultado foi impresso na saída como b'hell low word'? Isso significa que a saída está em bytes. Para ter a saída em texto plano, simplesmente utilize .decode('UTF-8') para decodificar a entrada que está no mesmo formato. Claro, existem montes de outros tipo como ISO8859-1, que já foi nosso padrão, mas aqui temos o tipo reconhecido no client. Em suma, a linha que exibe a mensagem no server deve ficar assim:
print(content.decode('UTF-8'))
E se for para enviar bytes invés de char? Simples também: use bytearray(). Apenas no client, faça isso:
#!/usr/bin/env python
import socket
#ip a se conectar
ip = "192.168.1.200"
#porta do socket server
port = 8888
addr = ((ip,port))
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(addr)
#exemplo de um array de bytes a enviar
msg = bytearray()
msg.append(94)
msg.append(0xff)
msg.append(1)
msg.append(0)
msg.append(0)
msg.append(0x0a)
client_socket.send(msg)
client_socket.close()
Assim a mensagem vai toda de uma vez já no formato que usaremos no robô da MASUGUX. Mas isso deixarei para detalhar no próprio artigo do robô.
Se for enviar do computador para o ESP8266 ou ESP32, duas considerações: não feche o socket imediatamente após o envio, senão o ESP8266 abortará. Para isso, coloque um delay antes de fechar a conexão. A outra consideração é que não devemos enviar o bytearray ou truncará. Nesse caso, devemos fazer um loop do tamanho do array e passar cada índice. Para saber o tamanho do array, use a função len(seuArrayDeBytes). Com o loop e o delay inclusos, o código fica assim:
#!/usr/bin/env python
import socket
import time
#ip a se conectar
ip = "192.168.1.208"
#porta do socket server
port = 123
addr = ((ip,port))
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(addr)
msg = bytearray()
msg.append(94)
msg.append(0xff)
msg.append(1)
msg.append(0)
msg.append(0)
msg.append(0x0a)
print(len(msg))
for i in range(6):
client_socket.send(str(msg[i]).encode())
time.sleep(1)
client_socket.close()
Podemos usar chr para interação, e talvez seja até melhor - porém, usando chr teremos um char assinalado, ou seja, de -127 à 127.
#!/usr/bin/env python
import socket
import time
import struct
#ip a se conectar
ip = "192.168.1.208"
#porta do socket server
port = 123
addr = ((ip,port))
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect(addr)
msg = bytearray()
msg.append(94)
msg.append(126)
msg.append(1)
msg.append(0)
msg.append(0)
msg.append(10)
for i in range(6):
client_socket.send(chr(msg[i]).encode())
time.sleep(1)
client_socket.close()
Para teste está bom.
Boas dicas, hum? Até a próxima!
Revisão: Ricardo Amaral de Andrade
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.