GitBook: [development_release] 23 pages modified

This commit is contained in:
Daniel Spindelbauer
2018-08-24 07:54:50 +00:00
committed by gitbook-bot
parent a1b62c0f5e
commit 30e81743e3
22 changed files with 473 additions and 41 deletions

137
tutorials/all/socket.md Normal file
View File

@@ -0,0 +1,137 @@
# Socket
Detailed information about this class can be found in [usocket](../../firmwareapi/micropython/usocket.md).
### Setting up a server with blocking sockets
The following example sets up a server which can accept 5 connections in parallel, create a new thread for each connected client, receives and sends back data then close the socket.
```python
import usocket
import _thread
import time
# Thread for handling a client
def client_thread(clientsocket,n):
# Receive maxium of 12 bytes from the client
r = clientsocket.recv(12)
# If recv() returns with 0 the other end closed the connection
if len(r) == 0:
clientsocket.close()
return
else:
# Do something wth the received data...
print("Received: {}".format(str(r)))
# Sends back some data
clientsocket.send(str(n))
# Close the socket and terminate the thread
clientsocket.close()
# Set up server socket
serversocket = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM)
serversocket.setsockopt(usocket.SOL_SOCKET, usocket.SO_REUSEADDR, 1)
serversocket.bind(("192.168.0.249", 6543))
# Accept maximum of 5 connections at the same time
serversocket.listen(5)
# Unique data to send back
c = 0
while True:
# Accept the connection of the clients
(clientsocket, address) = serversocket.accept()
# Start a new thread to handle the client
_thread.start_new_thread(client_thread, (clientsocket, c))
c = c+1
```
The following example sets up a client which can connect to a server with 2 non-blocking sockets, create a new thread to handle the non-blocking sockets.
```python
import socket
import _thread
import time
import uerrno
import uselect
def socket_thread(p):
while True:
# Wait for any action to happen infinitely
l = p.poll()
# Start processing the actions happened
for t in l:
# First element of the returned tuple is the socket itself
sock = t[0]
# Second element of the returned tuple is the events happened
event = t[1]
# If any error or connection drop happened close the socket
if(event & uselect.POLLERR or event & uselect.POLLHUP):
sock.close()
continue
# If the socket is writable then send some data
# The socket becomes writable if the connect() was successfull
if(event & uselect.POLLOUT):
# If any error occurs during sending here, do "nothing", poll() will return with error event, close the socket there
try:
sock.send("Data to send")
# We only want to send one message on this socket, in the future wait only for new incoming messages
p.modify(sock, uselect.POLLIN | uselect.POLLHUP | uselect.POLLERR)
except:
pass
# If any new data is received then get it
if(event & uselect.POLLIN):
# If any error occurs during receiving here, do "nothing", poll() will return with error event, close the socket there
try:
r = sock.recv(1)
# If recv() returns with 0 the other end closed the connection
if len(r) == 0:
sock.close()
continue
else:
# Do something with the received data...
print("Data received: " + str(r))
except:
pass
# List for storing our sockets
socket_list = []
# Set up the first socket in non-blocking mode
s1 = socket.socket()
s1.setblocking(False)
socket_list.append(s1)
# Set up the second socket in non-blocking mode
s2 = socket.socket()
s2.setblocking(False)
socket_list.append(s2)
# Create a new poll object
p = uselect.poll()
# Register the sockets into the poll object, wait for all kind of events
p.register(s1, uselect.POLLIN | uselect.POLLOUT | uselect.POLLHUP | uselect.POLLERR)
p.register(s2, uselect.POLLIN | uselect.POLLOUT | uselect.POLLHUP | uselect.POLLERR)
# Try to connect to the server with each sockets
for s in socket_list:
try:
s.connect(socket.getaddrinfo("192.168.0.234", 6543)[0][-1])
except OSError as e:
# In case of non-blocking socket the connect() raises eception of EINPROGRESS what is expected
if e.args[0] != uerrno.EINPROGRESS:
# Raise all other errors
raise
# Start the thread which takes care of the non-blocking sockets through the created poll object
_thread.start_new_thread(socket_thread, (p,))
```

125
tutorials/lora/lora-mesh.md Normal file
View File

@@ -0,0 +1,125 @@
# LoRa Mesh
The LoRa Mesh is implemented using [OpenThread](https://openthread.io/guides/thread-primer).
To understand the OpenThread terms and overall functionality, these guides are highly recommended:
* [What is Thread?](https://openthread.io/guides/thread-primer)
* [Node Roles and Types](https://openthread.io/guides/thread-primer/node-roles-and-types)
* [IPv6 Addressing](https://openthread.io/guides/thread-primer/ipv6-addressing) \(especially, RLOC unicast address\)
Important, all the OpenThread CLI commands are accessible using `LoRa.cli("command")`, the complete list of commands is [here](https://github.com/openthread/openthread/blob/master/src/cli/README.md). Please note some commands, can't execute, as some functionalities are not implemented \(ex: Commissioning Role, Joiner Role, DNS\).
This example shows how to:
* enable LoRa-Mesh network
* find neighbors \(parent, children, other router direct connections\)
* send PING to neighbors
* open UDP socket for:
* listening incoming UDP packets and answering back \(ACK\)
* sending packets to all neighbors
* toggle LED as packet/ping is received.
{% hint style="info" %}
The LoRa-Mesh socket supports only the following socket methods: `close()`, `bind()`, `sendto()`, and `recvfrom()`.
{% endhint %}
**Lora Mesh example**
* Source: [https://github.com/pycom/pycom-libraries/blob/master/lib/lora\_mesh/main.py](https://github.com/pycom/pycom-libraries/blob/master/lib/lora_mesh/main.py)
* `Loramesh` micropython library is available at [https://github.com/pycom/pycom-libraries/blob/master/lib/lora\_mesh/loramesh.py](https://github.com/pycom/pycom-libraries/blob/master/lib/lora_mesh/loramesh.py).
```python
from network import LoRa
import socket
import time
import utime
import ubinascii
import pycom
import machine
from loramesh import Loramesh
lora = LoRa(mode=LoRa.LORA, region=LoRa.EU868, bandwidth=LoRa.BW_125KHZ, sf=7)
MAC = str(ubinascii.hexlify(lora.mac()))[2:-1]
print("LoRa MAC: %s"%MAC)
mesh = Loramesh(lora)
# waiting until it connected to Mesh network and
# it has some valid neighbors
while True:
mesh.led_state()
print("%d: State %s, single %s"%(time.time(), mesh.cli('state'), mesh.cli('singleton')))
time.sleep(2)
if not mesh.is_connected():
continue
neigbors = mesh.neighbors_ip()
if len(neigbors) == 0:
print('No neighbor')
continue
print('Neighbors found: %s'%neigbors)
break
# create UDP socket
s = socket.socket(socket.AF_LORA, socket.SOCK_RAW)
myport = 1234
s.bind(myport)
pack_num = 1
msg = "Hello World! MAC: " + MAC + ", pack: "
ip = mesh.ip()
while True:
mesh.led_state()
print("%d: State %s, single %s, IP %s"%(time.time(), mesh.cli('state'), mesh.cli('singleton'), mesh.ip()))
# check if topology changes, maybe RLOC IPv6 changed
new_ip = mesh.ip()
if ip != new_ip:
print("IP changed from: %s to %s"%(ip, new_ip))
ip = new_ip
# listen for incomming packets
rcv_data, rcv_addr = s.recvfrom(128)
if len(rcv_data)>0:
rcv_ip = rcv_addr[0]
rcv_port = rcv_addr[1]
print('Incomming %d bytes from %s (port %d)'%(len(rcv_data), rcv_ip, rcv_port))
print(rcv_data)
# could send some ACK pack:
if rcv_data.startswith("Hello"):
try:
s.sendto('ACK ' + MAC + ' ' + str(rcv_data)[2:-1], (rcv_ip, rcv_port))
except Exception:
pass
mesh.blink(7, .3)
continue
# update neighbors list
neigbors = mesh.neighbors_ip()
print("%d Neighbors %s"%(len(neigbors), neigbors))
# send PING and UDP packets to all neighbors
for neighbor in neigbors:
if mesh.ping(neighbor) > 0:
print('Ping OK from neighbor %s'%neighbor)
mesh.blink(10, .1)
else:
print('Ping not received from neighbor %s'%neighbor)
time.sleep(10)
pack_num = pack_num + 1
try:
s.sendto(msg + str(pack_num), (neighbor, myport))
print('Sent message to %s'%(neighbor))
except Exception:
pass
time.sleep(20 + machine.rng()%20)
# random sleep time
time.sleep(30 + machine.rng()%30)
```